aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.12.589
-rw-r--r--dist/changes-5.13.1107
-rw-r--r--examples/HACKING23
-rw-r--r--examples/qml/doc/src/qml-extending.qdoc4
-rw-r--r--examples/qml/qmlextensionplugins/plugin.cpp3
-rw-r--r--examples/qml/referenceexamples/adding/main.cpp4
-rw-r--r--examples/qml/referenceexamples/adding/person.h3
-rw-r--r--examples/qml/referenceexamples/attached/birthdayparty.h10
-rw-r--r--examples/qml/referenceexamples/attached/main.cpp15
-rw-r--r--examples/qml/referenceexamples/attached/person.h5
-rw-r--r--examples/qml/referenceexamples/binding/birthdayparty.h5
-rw-r--r--examples/qml/referenceexamples/binding/main.cpp15
-rw-r--r--examples/qml/referenceexamples/binding/person.h5
-rw-r--r--examples/qml/referenceexamples/coercion/main.cpp15
-rw-r--r--examples/qml/referenceexamples/coercion/person.h6
-rw-r--r--examples/qml/referenceexamples/default/main.cpp12
-rw-r--r--examples/qml/referenceexamples/default/person.h4
-rw-r--r--examples/qml/referenceexamples/extended/main.cpp8
-rw-r--r--examples/qml/referenceexamples/grouped/main.cpp12
-rw-r--r--examples/qml/referenceexamples/grouped/person.h5
-rw-r--r--examples/qml/referenceexamples/methods/main.cpp9
-rw-r--r--examples/qml/referenceexamples/methods/person.h2
-rw-r--r--examples/qml/referenceexamples/properties/main.cpp9
-rw-r--r--examples/qml/referenceexamples/properties/person.h2
-rw-r--r--examples/qml/referenceexamples/signal/birthdayparty.h4
-rw-r--r--examples/qml/referenceexamples/signal/main.cpp14
-rw-r--r--examples/qml/referenceexamples/signal/person.h5
-rw-r--r--examples/qml/referenceexamples/valuesource/birthdayparty.h4
-rw-r--r--examples/qml/referenceexamples/valuesource/main.cpp15
-rw-r--r--examples/qml/referenceexamples/valuesource/person.h5
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h1
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h1
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp4
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h1
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h1
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h1
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h1
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h1
-rw-r--r--examples/quick/customitems/maskedmousearea/main.cpp2
-rw-r--r--examples/quick/customitems/maskedmousearea/maskedmousearea.h1
-rw-r--r--examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h2
-rw-r--r--examples/quick/customitems/painteditem/textballoon.h1
-rw-r--r--examples/quick/imageelements/doc/src/imageelements.qdoc4
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/fbitem.h1
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp2
-rw-r--r--examples/quick/quickwidgets/quickwidget/fbitem.h1
-rw-r--r--examples/quick/quickwidgets/quickwidget/main.cpp2
-rw-r--r--examples/quick/scenegraph/customgeometry/beziercurve.h1
-rw-r--r--examples/quick/scenegraph/customgeometry/main.cpp2
-rw-r--r--examples/quick/scenegraph/d3d11underqml/d3d11squircle.h1
-rw-r--r--examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro2
-rw-r--r--examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc6
-rw-r--r--examples/quick/scenegraph/d3d11underqml/main.cpp2
-rw-r--r--examples/quick/scenegraph/fboitem/CMakeLists.txt (renamed from examples/quick/scenegraph/textureinsgnode/CMakeLists.txt)0
-rw-r--r--examples/quick/scenegraph/fboitem/doc/images/fboitem-example.jpg (renamed from examples/quick/scenegraph/textureinsgnode/doc/images/textureinsgnode-example.jpg)bin25863 -> 25863 bytes
-rw-r--r--examples/quick/scenegraph/fboitem/doc/src/fboitem.qdoc (renamed from examples/quick/scenegraph/textureinsgnode/doc/src/textureinsgnode.qdoc)4
-rw-r--r--examples/quick/scenegraph/fboitem/fboinsgrenderer.cpp (renamed from examples/quick/scenegraph/textureinsgnode/fboinsgrenderer.cpp)0
-rw-r--r--examples/quick/scenegraph/fboitem/fboinsgrenderer.h (renamed from examples/quick/scenegraph/textureinsgnode/fboinsgrenderer.h)1
-rw-r--r--examples/quick/scenegraph/fboitem/fboitem.pro (renamed from examples/quick/scenegraph/textureinsgnode/textureinsgnode.pro)4
-rw-r--r--examples/quick/scenegraph/fboitem/fboitem.qrc (renamed from examples/quick/scenegraph/textureinsgnode/textureinsgnode.qrc)2
-rw-r--r--examples/quick/scenegraph/fboitem/main.cpp (renamed from examples/quick/scenegraph/textureinsgnode/main.cpp)4
-rw-r--r--examples/quick/scenegraph/fboitem/main.qml (renamed from examples/quick/scenegraph/textureinsgnode/main.qml)0
-rw-r--r--examples/quick/scenegraph/graph/graph.h1
-rw-r--r--examples/quick/scenegraph/graph/main.cpp2
-rw-r--r--examples/quick/scenegraph/metaltextureimport/doc/images/metaltextureimport-example.jpgbin0 -> 44545 bytes
-rw-r--r--examples/quick/scenegraph/metaltextureimport/doc/src/metaltextureimport.qdoc101
-rw-r--r--examples/quick/scenegraph/metaltextureimport/main.cpp70
-rw-r--r--examples/quick/scenegraph/metaltextureimport/main.qml123
-rw-r--r--examples/quick/scenegraph/metaltextureimport/metaltextureimport.h88
-rw-r--r--examples/quick/scenegraph/metaltextureimport/metaltextureimport.mm424
-rw-r--r--examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro12
-rw-r--r--examples/quick/scenegraph/metaltextureimport/metaltextureimport.qrc7
-rw-r--r--examples/quick/scenegraph/metaltextureimport/squircle.frag29
-rw-r--r--examples/quick/scenegraph/metaltextureimport/squircle.vert23
-rw-r--r--examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc7
-rw-r--r--examples/quick/scenegraph/metalunderqml/main.cpp2
-rw-r--r--examples/quick/scenegraph/metalunderqml/metalsquircle.h1
-rw-r--r--examples/quick/scenegraph/metalunderqml/metalsquircle.mm13
-rw-r--r--examples/quick/scenegraph/metalunderqml/metalunderqml.pro2
-rw-r--r--examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc7
-rw-r--r--examples/quick/scenegraph/openglunderqml/main.cpp2
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.h1
-rw-r--r--examples/quick/scenegraph/rendernode/customrenderitem.cpp62
-rw-r--r--examples/quick/scenegraph/rendernode/customrenderitem.h1
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.cpp28
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.h11
-rw-r--r--examples/quick/scenegraph/rendernode/main.cpp2
-rw-r--r--examples/quick/scenegraph/rendernode/metalrenderer.h16
-rw-r--r--examples/quick/scenegraph/rendernode/metalrenderer.mm33
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.cpp17
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.h8
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.cpp26
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.h7
-rw-r--r--examples/quick/scenegraph/scenegraph.pro10
-rw-r--r--examples/quick/scenegraph/simplematerial/simplematerial.cpp3
-rw-r--r--examples/quick/scenegraph/textureinthread/main.cpp2
-rw-r--r--examples/quick/scenegraph/textureinthread/threadrenderer.h1
-rw-r--r--examples/quick/scenegraph/threadedanimation/main.cpp2
-rw-r--r--examples/quick/scenegraph/threadedanimation/spinner.h1
-rw-r--r--examples/quick/scenegraph/twotextureproviders/main.cpp2
-rw-r--r--examples/quick/scenegraph/twotextureproviders/xorblender.h1
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/doc/images/vulkanunderqml-example.jpgbin0 -> 39962 bytes
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/doc/src/vulkanunderqml.qdoc68
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/main.cpp70
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/main.qml89
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/squircle.frag.spvbin0 -> 1432 bytes
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/squircle.vert.spvbin0 -> 644 bytes
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp623
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h86
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro10
-rw-r--r--examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.qrc7
-rw-r--r--examples/quick/shapes/content/interactive.qml113
-rw-r--r--examples/quick/tableview/gameoflife/gameoflifemodel.h2
-rw-r--r--examples/quick/tableview/gameoflife/main.cpp2
-rw-r--r--examples/quick/tableview/pixelator/imagemodel.h2
-rw-r--r--examples/quick/tableview/pixelator/main.cpp2
-rw-r--r--examples/quick/views/doc/src/views.qdoc2
-rw-r--r--src/imports/builtins/builtins.qmltypes11
-rw-r--r--src/imports/folderlistmodel/plugin.cpp13
-rw-r--r--src/imports/folderlistmodel/plugins.qmltypes274
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp14
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.h1
-rw-r--r--src/imports/imports.pro2
-rw-r--r--src/imports/labsanimation/labsanimation.pro4
-rw-r--r--src/imports/labsanimation/plugin.cpp4
-rw-r--r--src/imports/labsanimation/plugins.qmltypes4
-rw-r--r--src/imports/labsanimation/qquickboundaryrule.cpp (renamed from src/quick/util/qquickboundaryrule.cpp)0
-rw-r--r--src/imports/labsanimation/qquickboundaryrule_p.h (renamed from src/quick/util/qquickboundaryrule_p.h)3
-rw-r--r--src/imports/layouts/plugin.cpp11
-rw-r--r--src/imports/layouts/plugins.qmltypes49
-rw-r--r--src/imports/layouts/qquicklayout_p.h5
-rw-r--r--src/imports/layouts/qquicklinearlayout_p.h5
-rw-r--r--src/imports/layouts/qquickstacklayout.cpp2
-rw-r--r--src/imports/layouts/qquickstacklayout_p.h2
-rw-r--r--src/imports/localstorage/localstorage.pro7
-rw-r--r--src/imports/localstorage/plugin.cpp775
-rw-r--r--src/imports/localstorage/qquicklocalstorage.cpp792
-rw-r--r--src/imports/localstorage/qquicklocalstorage_p.h75
-rw-r--r--src/imports/models/plugins.qmltypes66
-rw-r--r--src/imports/particles/plugins.qmltypes220
-rw-r--r--src/imports/qtqml/plugins.qmltypes26
-rw-r--r--src/imports/qtquick2/plugins.qmltypes727
-rw-r--r--src/imports/settings/plugin.cpp2
-rw-r--r--src/imports/settings/qqmlsettings.cpp2
-rw-r--r--src/imports/settings/qqmlsettings_p.h1
-rw-r--r--src/imports/shapes/plugin.cpp15
-rw-r--r--src/imports/shapes/plugins.qmltypes38
-rw-r--r--src/imports/statemachine/finalstate.h2
-rw-r--r--src/imports/statemachine/plugin.cpp14
-rw-r--r--src/imports/statemachine/plugins.qmltypes14
-rw-r--r--src/imports/statemachine/signaltransition.h7
-rw-r--r--src/imports/statemachine/state.h2
-rw-r--r--src/imports/statemachine/statemachine.h2
-rw-r--r--src/imports/statemachine/statemachine.pro3
-rw-r--r--src/imports/statemachine/statemachineforeign.h80
-rw-r--r--src/imports/statemachine/timeouttransition.h2
-rw-r--r--src/imports/testlib/main.cpp101
-rw-r--r--src/imports/testlib/plugins.qmltypes2
-rw-r--r--src/imports/wavefrontmesh/plugin.cpp2
-rw-r--r--src/imports/wavefrontmesh/qwavefrontmesh.h2
-rw-r--r--src/imports/window/plugins.qmltypes17
-rw-r--r--src/particles/qquickage_p.h1
-rw-r--r--src/particles/qquickangledirection_p.h3
-rw-r--r--src/particles/qquickcumulativedirection_p.h3
-rw-r--r--src/particles/qquickcustomaffector.cpp2
-rw-r--r--src/particles/qquickcustomaffector_p.h4
-rw-r--r--src/particles/qquickcustomparticle_p.h1
-rw-r--r--src/particles/qquickdirection_p.h4
-rw-r--r--src/particles/qquickellipseextruder_p.h1
-rw-r--r--src/particles/qquickfriction_p.h1
-rw-r--r--src/particles/qquickgravity_p.h2
-rw-r--r--src/particles/qquickgroupgoal_p.h1
-rw-r--r--src/particles/qquickimageparticle.cpp20
-rw-r--r--src/particles/qquickimageparticle_p.h1
-rw-r--r--src/particles/qquickitemparticle.cpp20
-rw-r--r--src/particles/qquickitemparticle_p.h4
-rw-r--r--src/particles/qquicklineextruder_p.h1
-rw-r--r--src/particles/qquickmaskextruder.cpp4
-rw-r--r--src/particles/qquickmaskextruder_p.h5
-rw-r--r--src/particles/qquickparticleaffector.cpp2
-rw-r--r--src/particles/qquickparticleaffector_p.h3
-rw-r--r--src/particles/qquickparticleemitter.cpp15
-rw-r--r--src/particles/qquickparticleemitter_p.h1
-rw-r--r--src/particles/qquickparticleextruder_p.h4
-rw-r--r--src/particles/qquickparticlegroup_p.h1
-rw-r--r--src/particles/qquickparticlepainter_p.h3
-rw-r--r--src/particles/qquickparticlesmodule.cpp64
-rw-r--r--src/particles/qquickparticlesystem_p.h1
-rw-r--r--src/particles/qquickpointattractor_p.h1
-rw-r--r--src/particles/qquickpointdirection_p.h1
-rw-r--r--src/particles/qquickrectangleextruder_p.h1
-rw-r--r--src/particles/qquickspritegoal_p.h1
-rw-r--r--src/particles/qquicktargetdirection_p.h3
-rw-r--r--src/particles/qquicktrailemitter_p.h1
-rw-r--r--src/particles/qquickturbulence_p.h4
-rw-r--r--src/particles/qquickwander_p.h1
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp61
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h3
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp7
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp4
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp2
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp17
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp3
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp2
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgspritenode.h2
-rw-r--r--src/qml/common/qqmlapiversion_p.h2
-rw-r--r--src/qml/common/qv4compileddata_p.h5
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp15
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h2
-rw-r--r--src/qml/doc/qtqml.qdocconf10
-rw-r--r--src/qml/doc/src/cppintegration/extending-tutorial.qdoc3
-rw-r--r--src/qml/doc/src/javascript/finetuning.qdoc104
-rw-r--r--src/qml/doc/src/javascript/imports.qdoc7
-rw-r--r--src/qml/doc/src/javascript/qtjavascript.qdoc7
-rw-r--r--src/qml/doc/src/javascript/string.qdoc4
-rw-r--r--src/qml/doc/src/javascript/topic.qdoc7
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc45
-rw-r--r--src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc5
-rw-r--r--src/qml/jit/qv4assemblercommon_p.h2
-rw-r--r--src/qml/jit/qv4baselineassembler.cpp7
-rw-r--r--src/qml/jit/qv4baselineassembler_p.h1
-rw-r--r--src/qml/jit/qv4baselinejit.cpp16
-rw-r--r--src/qml/jsapi/qjsengine.cpp4
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp44
-rw-r--r--src/qml/jsruntime/qv4engine.cpp22
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp10
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h13
-rw-r--r--src/qml/jsruntime/qv4promiseobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp31
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h1
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp8
-rw-r--r--src/qml/parser/qqmljs.g204
-rw-r--r--src/qml/parser/qqmljsast.cpp6
-rw-r--r--src/qml/parser/qqmljsast_p.h75
-rw-r--r--src/qml/parser/qqmljskeywords_p.h12
-rw-r--r--src/qml/parser/qqmljslexer.cpp82
-rw-r--r--src/qml/qml/ftw/qintrusivelist.cpp4
-rw-r--r--src/qml/qml/qqml.cpp190
-rw-r--r--src/qml/qml/qqml.h125
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp2
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp141
-rw-r--r--src/qml/qml/qqmlcomponent.h27
-rw-r--r--src/qml/qml/qqmlcomponent_p.h8
-rw-r--r--src/qml/qml/qqmlcomponentattached_p.h5
-rw-r--r--src/qml/qml/qqmlcontext.cpp4
-rw-r--r--src/qml/qml/qqmlcontext_p.h11
-rw-r--r--src/qml/qml/qqmldatablob.cpp2
-rw-r--r--src/qml/qml/qqmldatablob_p.h2
-rw-r--r--src/qml/qml/qqmldirdata.cpp2
-rw-r--r--src/qml/qml/qqmlengine.cpp26
-rw-r--r--src/qml/qml/qqmlengine_p.h7
-rw-r--r--src/qml/qml/qqmlglobal_p.h16
-rw-r--r--src/qml/qml/qqmlimport.cpp49
-rw-r--r--src/qml/qml/qqmlimport_p.h2
-rw-r--r--src/qml/qml/qqmlincubator.cpp58
-rw-r--r--src/qml/qml/qqmlincubator.h5
-rw-r--r--src/qml/qml/qqmlincubator_p.h9
-rw-r--r--src/qml/qml/qqmlinfo.cpp6
-rw-r--r--src/qml/qml/qqmllocale_p.h3
-rw-r--r--src/qml/qml/qqmlloggingcategory_p.h3
-rw-r--r--src/qml/qml/qqmlmetatype.cpp54
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp3
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h4
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp55
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h27
-rw-r--r--src/qml/qml/qqmlprivate.h392
-rw-r--r--src/qml/qml/qqmlproperty.cpp2
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h100
-rw-r--r--src/qml/qml/qqmlpropertyvalidator.cpp59
-rw-r--r--src/qml/qml/qqmlscriptblob.cpp4
-rw-r--r--src/qml/qml/qqmlscriptdata.cpp6
-rw-r--r--src/qml/qml/qqmlscriptdata_p.h2
-rw-r--r--src/qml/qml/qqmltype.cpp86
-rw-r--r--src/qml/qml/qqmltype_p.h5
-rw-r--r--src/qml/qml/qqmltype_p_p.h22
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp74
-rw-r--r--src/qml/qml/qqmltypedata.cpp7
-rw-r--r--src/qml/qml/qqmltypeloader.cpp14
-rw-r--r--src/qml/qml/qqmltypeloaderqmldircontent.cpp3
-rw-r--r--src/qml/qml/qqmltypenotavailable_p.h3
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp56
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp51
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h5
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp86
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h37
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp35
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp246
-rw-r--r--src/qml/qmldirparser/qqmldirparser.cpp8
-rw-r--r--src/qml/qmldirparser/qqmldirparser_p.h19
-rw-r--r--src/qml/types/qqmlbind.cpp83
-rw-r--r--src/qml/types/qqmlbind_p.h10
-rw-r--r--src/qml/types/qqmlconnections_p.h8
-rw-r--r--src/qml/types/qqmltimer_p.h1
-rw-r--r--src/qml/util/qqmlpropertymap.cpp4
-rw-r--r--src/qmldebug/qqmldebugconnection.cpp27
-rw-r--r--src/qmldebug/qqmldebugconnection_p.h1
-rw-r--r--src/qmldebug/qqmlenginedebugclient.cpp130
-rw-r--r--src/qmldebug/qqmlenginedebugclient_p.h90
-rw-r--r--src/qmldebug/qqmlenginedebugclient_p_p.h2
-rw-r--r--src/qmlmodels/doc/qtqmlmodels.qdocconf37
-rw-r--r--src/qmlmodels/doc/snippets/delegatemodel/delegatemodel.qml (renamed from src/qml/doc/snippets/delegatemodel/delegatemodel.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/delegatemodel/delegatemodel_rootindex/main.cpp (renamed from src/qml/doc/snippets/delegatemodel/delegatemodel_rootindex/main.cpp)0
-rw-r--r--src/qmlmodels/doc/snippets/delegatemodel/delegatemodel_rootindex/view.qml (renamed from src/qml/doc/snippets/delegatemodel/delegatemodel_rootindex/view.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/delegatemodel/delegatemodelgroup.qml (renamed from src/qml/doc/snippets/delegatemodel/delegatemodelgroup.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/package/Delegate.qml (renamed from src/qml/doc/snippets/package/Delegate.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/package/view.qml (renamed from src/qml/doc/snippets/package/view.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/listmodel/listelements.qml (renamed from src/qml/doc/snippets/qml/listmodel/listelements.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/listmodel/listmodel-modify.qml (renamed from src/qml/doc/snippets/qml/listmodel/listmodel-modify.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/listmodel/listmodel-nested.qml (renamed from src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/listmodel/listmodel-simple.qml (renamed from src/qml/doc/snippets/qml/listmodel/listmodel-simple.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/listmodel/listmodel.qml (renamed from src/qml/doc/snippets/qml/listmodel/listmodel.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-complex.qml (renamed from src/qml/doc/snippets/qml/tablemodel/fruit-example-complex.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml (renamed from src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml)0
-rw-r--r--src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml (renamed from src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml)0
-rw-r--r--src/qmlmodels/qmlmodels.pro2
-rw-r--r--src/qmlmodels/qqmldelegatecomponent.cpp13
-rw-r--r--src/qmlmodels/qqmldelegatecomponent_p.h5
-rw-r--r--src/qmlmodels/qqmldelegatemodel.cpp132
-rw-r--r--src/qmlmodels/qqmldelegatemodel_p.h10
-rw-r--r--src/qmlmodels/qqmldelegatemodel_p_p.h16
-rw-r--r--src/qmlmodels/qqmlinstantiator.cpp5
-rw-r--r--src/qmlmodels/qqmlinstantiator_p.h2
-rw-r--r--src/qmlmodels/qqmlitemmodels.qdoc2
-rw-r--r--src/qmlmodels/qqmllistmodel.cpp33
-rw-r--r--src/qmlmodels/qqmllistmodel_p.h10
-rw-r--r--src/qmlmodels/qqmllistmodel_p_p.h4
-rw-r--r--src/qmlmodels/qqmllistmodelworkeragent_p.h2
-rw-r--r--src/qmlmodels/qqmlmodelsmodule.cpp29
-rw-r--r--src/qmlmodels/qqmlmodelsmodule_p.h16
-rw-r--r--src/qmlmodels/qqmlobjectmodel.cpp8
-rw-r--r--src/qmlmodels/qqmlobjectmodel_p.h5
-rw-r--r--src/qmlmodels/qqmltableinstancemodel.cpp9
-rw-r--r--src/qmlmodels/qqmltablemodel.cpp2
-rw-r--r--src/qmlmodels/qqmltablemodel_p.h1
-rw-r--r--src/qmlmodels/qqmltablemodelcolumn_p.h1
-rw-r--r--src/qmlmodels/qquickpackage.cpp7
-rw-r--r--src/qmlmodels/qquickpackage_p.h3
-rw-r--r--src/qmltest/qmltest.pro5
-rw-r--r--src/qmltest/quicktestevent_p.h4
-rw-r--r--src/qmltest/quicktestresult_p.h2
-rw-r--r--src/qmltest/quicktestutil.cpp111
-rw-r--r--src/qmltest/quicktestutil_p.h89
-rw-r--r--src/qmlworkerscript/doc/qtqmlworkerscript.qdocconf37
-rw-r--r--src/qmlworkerscript/qmlworkerscript.pro2
-rw-r--r--src/qmlworkerscript/qqmlworkerscriptmodule.cpp2
-rw-r--r--src/qmlworkerscript/qquickworkerscript.cpp4
-rw-r--r--src/qmlworkerscript/qquickworkerscript_p.h1
-rw-r--r--src/quick/doc/qtquick.qdocconf4
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc2
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc26
-rw-r--r--src/quick/doc/src/examples.qdoc7
-rw-r--r--src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc16
-rw-r--r--src/quick/doc/src/guidelines/qtquick-toolsnutilities.qdoc6
-rw-r--r--src/quick/doc/src/qtquick.qdoc2
-rw-r--r--src/quick/handlers/qquickdragaxis_p.h4
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp3
-rw-r--r--src/quick/handlers/qquickdraghandler_p.h2
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp35
-rw-r--r--src/quick/handlers/qquickhoverhandler_p.h2
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp2
-rw-r--r--src/quick/handlers/qquickmultipointhandler_p.h2
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp7
-rw-r--r--src/quick/handlers/qquickpinchhandler_p.h2
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler.cpp51
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp69
-rw-r--r--src/quick/handlers/qquickpointerhandler_p.h10
-rw-r--r--src/quick/handlers/qquickpointerhandler_p_p.h7
-rw-r--r--src/quick/handlers/qquickpointhandler_p.h2
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp19
-rw-r--r--src/quick/handlers/qquicktaphandler_p.h3
-rw-r--r--src/quick/handlers/qquickwheelhandler_p.h3
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp58
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h1
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp179
-rw-r--r--src/quick/items/qquickaccessibleattached_p.h5
-rw-r--r--src/quick/items/qquickanchors_p.h1
-rw-r--r--src/quick/items/qquickanimatedimage.cpp3
-rw-r--r--src/quick/items/qquickanimatedimage_p.h2
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp2
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h5
-rw-r--r--src/quick/items/qquickborderimage.cpp2
-rw-r--r--src/quick/items/qquickborderimage_p.h1
-rw-r--r--src/quick/items/qquickborderimage_p_p.h2
-rw-r--r--src/quick/items/qquickdrag.cpp6
-rw-r--r--src/quick/items/qquickdrag_p.h8
-rw-r--r--src/quick/items/qquickdroparea.cpp4
-rw-r--r--src/quick/items/qquickdroparea_p.h3
-rw-r--r--src/quick/items/qquickevents.cpp7
-rw-r--r--src/quick/items/qquickevents_p_p.h30
-rw-r--r--src/quick/items/qquickflickable.cpp4
-rw-r--r--src/quick/items/qquickflickable_p.h1
-rw-r--r--src/quick/items/qquickflickable_p_p.h1
-rw-r--r--src/quick/items/qquickflickablebehavior_p.h5
-rw-r--r--src/quick/items/qquickflipable_p.h1
-rw-r--r--src/quick/items/qquickfocusscope_p.h1
-rw-r--r--src/quick/items/qquickgraphicsinfo_p.h7
-rw-r--r--src/quick/items/qquickgridview.cpp24
-rw-r--r--src/quick/items/qquickgridview_p.h3
-rw-r--r--src/quick/items/qquickimage.cpp4
-rw-r--r--src/quick/items/qquickimage_p.h1
-rw-r--r--src/quick/items/qquickimagebase_p.h4
-rw-r--r--src/quick/items/qquickitem.cpp5
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h22
-rw-r--r--src/quick/items/qquickitemanimation_p.h3
-rw-r--r--src/quick/items/qquickitemgrabresult.h3
-rw-r--r--src/quick/items/qquickitemsmodule.cpp443
-rw-r--r--src/quick/items/qquickitemsmodule_p.h10
-rw-r--r--src/quick/items/qquickitemview.cpp55
-rw-r--r--src/quick/items/qquickitemview_p.h4
-rw-r--r--src/quick/items/qquickitemview_p_p.h2
-rw-r--r--src/quick/items/qquickitemviewtransition_p.h5
-rw-r--r--src/quick/items/qquicklistview.cpp52
-rw-r--r--src/quick/items/qquicklistview_p.h4
-rw-r--r--src/quick/items/qquickloader.cpp4
-rw-r--r--src/quick/items/qquickloader_p.h1
-rw-r--r--src/quick/items/qquickmousearea.cpp4
-rw-r--r--src/quick/items/qquickmousearea_p.h1
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp6
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h5
-rw-r--r--src/quick/items/qquickopenglinfo_p.h7
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp4
-rw-r--r--src/quick/items/qquickpainteditem.h3
-rw-r--r--src/quick/items/qquickpathview.cpp180
-rw-r--r--src/quick/items/qquickpathview_p.h3
-rw-r--r--src/quick/items/qquickpincharea_p.h3
-rw-r--r--src/quick/items/qquickpositioners_p.h11
-rw-r--r--src/quick/items/qquickrectangle_p.h4
-rw-r--r--src/quick/items/qquickrendercontrol.cpp4
-rw-r--r--src/quick/items/qquickrepeater_p.h1
-rw-r--r--src/quick/items/qquickscalegrid_p_p.h1
-rw-r--r--src/quick/items/qquickscreen.cpp3
-rw-r--r--src/quick/items/qquickscreen_p.h9
-rw-r--r--src/quick/items/qquickshadereffect_p.h1
-rw-r--r--src/quick/items/qquickshadereffectmesh_p.h10
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h1
-rw-r--r--src/quick/items/qquicksprite_p.h1
-rw-r--r--src/quick/items/qquickspritesequence_p.h1
-rw-r--r--src/quick/items/qquickstateoperations.cpp101
-rw-r--r--src/quick/items/qquickstateoperations_p.h15
-rw-r--r--src/quick/items/qquicktableview.cpp20
-rw-r--r--src/quick/items/qquicktableview_p.h9
-rw-r--r--src/quick/items/qquicktext_p.h2
-rw-r--r--src/quick/items/qquicktextcontrol.cpp16
-rw-r--r--src/quick/items/qquicktextcontrol_p.h2
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h2
-rw-r--r--src/quick/items/qquicktextdocument.h1
-rw-r--r--src/quick/items/qquicktextedit.cpp6
-rw-r--r--src/quick/items/qquicktextedit_p.h1
-rw-r--r--src/quick/items/qquicktextinput.cpp27
-rw-r--r--src/quick/items/qquicktextinput_p.h3
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp12
-rw-r--r--src/quick/items/qquicktranslate_p.h5
-rw-r--r--src/quick/items/qquickwindow.cpp166
-rw-r--r--src/quick/items/qquickwindow.h9
-rw-r--r--src/quick/items/qquickwindow_p.h24
-rw-r--r--src/quick/items/qquickwindowmodule.cpp17
-rw-r--r--src/quick/items/qquickwindowmodule_p.h4
-rw-r--r--src/quick/qtquick2.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp5
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h3
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp5
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp48
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer.h10
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp39
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h14
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp105
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialrhishader.h12
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.cpp36
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.h3
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.cpp3
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.h1
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp5
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h1
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp38
-rw-r--r--src/quick/scenegraph/qsgdefaultinternalimagenode.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp8
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h19
-rw-r--r--src/quick/scenegraph/qsgdefaultspritenode.cpp8
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp28
-rw-r--r--src/quick/scenegraph/qsgopengllayer.cpp2
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp90
-rw-r--r--src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp4
-rw-r--r--src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h2
-rw-r--r--src/quick/scenegraph/qsgrhilayer.cpp5
-rw-r--r--src/quick/scenegraph/qsgrhishadereffectnode.cpp12
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp43
-rw-r--r--src/quick/scenegraph/qsgrhisupport_p.h3
-rw-r--r--src/quick/scenegraph/qsgrhitextureglyphcache.cpp4
-rw-r--r--src/quick/scenegraph/qsgrhitextureglyphcache_p.h2
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp166
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/scenegraph.pri8
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.cpp4
-rw-r--r--src/quick/scenegraph/util/qsgrhiatlastexture.cpp7
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial_p.h6
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.cpp4
-rw-r--r--src/quick/util/qquickanimation.cpp2
-rw-r--r--src/quick/util/qquickanimation_p.h13
-rw-r--r--src/quick/util/qquickanimationcontroller_p.h1
-rw-r--r--src/quick/util/qquickanimator_p.h16
-rw-r--r--src/quick/util/qquickanimatorjob.cpp2
-rw-r--r--src/quick/util/qquickapplication_p.h3
-rw-r--r--src/quick/util/qquickbehavior_p.h1
-rw-r--r--src/quick/util/qquickfontloader_p.h1
-rw-r--r--src/quick/util/qquickfontmetrics.cpp7
-rw-r--r--src/quick/util/qquickfontmetrics_p.h2
-rw-r--r--src/quick/util/qquickforeignutils_p.h120
-rw-r--r--src/quick/util/qquickpath_p.h21
-rw-r--r--src/quick/util/qquickpathinterpolator_p.h1
-rw-r--r--src/quick/util/qquickpropertychanges_p.h7
-rw-r--r--src/quick/util/qquickshortcut.cpp2
-rw-r--r--src/quick/util/qquickshortcut_p.h3
-rw-r--r--src/quick/util/qquicksmoothedanimation_p.h1
-rw-r--r--src/quick/util/qquickspringanimation_p.h1
-rw-r--r--src/quick/util/qquickstate_p.h2
-rw-r--r--src/quick/util/qquickstatechangescript_p.h1
-rw-r--r--src/quick/util/qquickstategroup.cpp2
-rw-r--r--src/quick/util/qquickstategroup_p.h1
-rw-r--r--src/quick/util/qquicksystempalette_p.h1
-rw-r--r--src/quick/util/qquicktextmetrics_p.h2
-rw-r--r--src/quick/util/qquicktransition_p.h1
-rw-r--r--src/quick/util/qquickutilmodule.cpp112
-rw-r--r--src/quick/util/qquickvalidator_p.h2
-rw-r--r--src/quick/util/qquickvaluetypes.cpp5
-rw-r--r--src/quick/util/qquickvaluetypes_p.h5
-rw-r--r--src/quick/util/util.pri5
-rw-r--r--src/quickshapes/qquickshape.cpp12
-rw-r--r--src/quickshapes/qquickshape_p.h8
-rw-r--r--src/quickshapes/qquickshapegenericrenderer.cpp12
-rw-r--r--src/quickshapes/qquickshapegenericrenderer_p.h12
-rw-r--r--src/quickshapes/qquickshapenvprrenderer.cpp10
-rw-r--r--src/quickwidgets/qquickwidget.cpp18
-rw-r--r--src/quickwidgets/qquickwidget_p.h1
-rw-r--r--tests/auto/qml/qmlcachegen/data/module.mjs6
-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/data/utils.mjs4
-rw-r--r--tests/auto/qml/qmlcachegen/qmlcachegen.pro6
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp30
-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/Things/SomethingElse.qml2
-rw-r--r--tests/auto/qml/qmllint/data/Things/plugins.qmltypes16
-rw-r--r--tests/auto/qml/qmllint/data/Things/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/UnmatchedSignalHandler.qml15
-rw-r--r--tests/auto/qml/qmllint/data/forLoop.qml9
-rw-r--r--tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml6
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp158
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp2
-rw-r--r--tests/auto/qml/qqmlbinding/data/noUnexpectedStringConversion.qml30
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp64
-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/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/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.cpp113
-rw-r--r--tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp2
-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/qqmlcpputils/tst_qqmlcpputils.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-October.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml16
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h8
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp189
-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/tst_qqmlengine.cpp35
-rw-r--r--tests/auto/qml/qqmlincubator/data/requiredProperty.qml5
-rw-r--r--tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp39
-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/alias.17.qml31
-rw-r--r--tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/foreignExtended.qml20
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt2
-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.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp4
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h34
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp175
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp57
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/multiSingleton.qml6
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml17
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton2.qml6
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/internal/InternalType.qml6
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/moduleWithQmlSingleton.pro18
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp50
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/qmldir2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp4
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro3
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp17
-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/qqmlpromise/data/promisehandlerthrows.qml17
-rw-r--r--tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp12
-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/tst_qqmlproperty.cpp26
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/SpecialObject1.qml5
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/SpecialObject2.qml5
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/noDuckType.qml7
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp11
-rw-r--r--tests/auto/qml/qqmlqt/data/formatting.qml5
-rw-r--r--tests/auto/qml/qqmlqt/data/timeRoundtrip.qml2
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp19
-rw-r--r--tests/auto/qml/qqmltranslation/data/mylibrary.js5
-rw-r--r--tests/auto/qml/qqmltranslation/data/nested_js_translation.js3
-rw-r--r--tests/auto/qml/qqmltranslation/data/preferjs.qml8
-rw-r--r--tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp23
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml5
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml6
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir2
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp20
-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/color_read.qml3
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h3
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp16
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp42
-rw-r--r--tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp25
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp99
-rw-r--r--tests/auto/quick/qquickanimatedimage/data/currentframe.qml13
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp46
-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/qquickdrag/tst_qquickdrag.cpp8
-rw-r--r--tests/auto/quick/qquickdroparea/data/nested1.qml93
-rw-r--r--tests/auto/quick/qquickdroparea/data/nested2.qml93
-rw-r--r--tests/auto/quick/qquickdroparea/qquickdroparea.pro7
-rw-r--r--tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp88
-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/qquicklayouts/data/tst_gridlayout.qml95
-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/tst_qquicklistview.cpp125
-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/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickmousearea/data/dragreset.qml1
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp34
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp37
-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/data/nestedmousearea2.qml101
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp103
-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/qquickrepeater/data/objlist_required.qml23
-rw-r--r--tests/auto/quick/qquickrepeater/data/requiredProperty.qml16
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp25
-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/data/tweakimplicitsize.qml89
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp72
-rw-r--r--tests/auto/quick/qquicktext/data/transparentBackground.qml16
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp22
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp23
-rw-r--r--tests/auto/quick/qquicktextinput/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp40
-rw-r--r--tests/auto/quick/qquickwindow/data/shortcut.qml47
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp28
-rw-r--r--tests/manual/nodetypes_ng/nodetypes_ng.cpp7
-rw-r--r--tests/manual/pointer/pointerDrag.qml65
-rw-r--r--tests/manual/pointer/tapWithModifiers.qml14
-rw-r--r--tests/manual/scenegraph_lancelot/hostinfo.sh76
-rw-r--r--tests/manual/scenegraph_lancelot/scenegrabber/main.cpp9
-rw-r--r--tests/manual/scenegraph_lancelot/scenegraph/scenegraph.pro4
-rw-r--r--tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp24
-rw-r--r--tools/qml/conf.h3
-rw-r--r--tools/qml/main.cpp17
-rw-r--r--tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in10
-rw-r--r--tools/qmlcachegen/generateloader.cpp233
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp16
-rw-r--r--tools/qmlcachegen/qtquickcompiler.prf45
-rw-r--r--tools/qmlcachegen/resourcefilter.cpp51
-rw-r--r--tools/qmllint/fakemetaobject.cpp14
-rw-r--r--tools/qmllint/fakemetaobject.h3
-rw-r--r--tools/qmllint/findunqualified.cpp205
-rw-r--r--tools/qmllint/findunqualified.h7
-rw-r--r--tools/qmllint/main.cpp9
-rw-r--r--tools/qmllint/qcoloroutput.cpp11
-rw-r--r--tools/qmllint/qcoloroutput_p.h2
-rw-r--r--tools/qmllint/qmljstypedescriptionreader.cpp67
-rw-r--r--tools/qmllint/scopetree.cpp44
-rw-r--r--tools/qmllint/scopetree.h5
-rw-r--r--tools/qmlplugindump/main.cpp74
-rw-r--r--tools/qmlplugindump/qmlstreamwriter.cpp16
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.cpp4
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.cpp1
-rw-r--r--tools/qmltime/qmltime.cpp2
784 files changed, 13869 insertions, 4653 deletions
diff --git a/dist/changes-5.12.5 b/dist/changes-5.12.5
new file mode 100644
index 0000000000..be0621c138
--- /dev/null
+++ b/dist/changes-5.12.5
@@ -0,0 +1,89 @@
+Qt 5.12.5 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.4.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+ - [QTBUG-76871] TapHandler.point now holds the release position while the
+ tapped() signal is emitted.
+
+****************************************************************************
+* QtQml *
+****************************************************************************
+
+ - [QTBUG-76018] Readonly QML properties can now be templates such as
+ list<...>.
+ - [QTBUG-76085] QQmlApplication engine now automatically loads translation
+ files from resource directories.
+ - [QTBUG-75939] Instances of QJSValue can now safely be passed between
+ threads and destroyed in a different thread.
+ - [QTBUG-75642] Fixed an invalid memory read caused by the JIT compiler.
+ - [QTBUG-71387] Fixed a use-after-free condition caused by calling
+ qmlClearTypeRegistrations().
+ - [QTBUG-76656] Made sure JavaScript "this" points to the right object when
+ calling scope and context properties through lookups.
+ - [QTBUG-76796] Fixed bindings to typeof(<name>) to get re-evaluated when
+ <name> gets defined.
+ - [QTBUG-55407] Avoid invalid memory access when calling setData() on a
+ QQmlComponent constructed without an engine.
+ - [QTBUG-76441] Fixed importing "qrc:/" (with exactly one slash).
+ - [QTBUG-71329] Implemented the missing bits of JavaScript promise chains.
+ - [QTBUG-75983] Fixed null pointer dereference in QQmlXmlHttpRequest.
+ - [QTBUG-77012] Fixed static build issue: multiple definitions of
+ qtPositionAttributeName().
+ - [QTBUG-77102] The component versioning is not enforced when loading
+ singletons.
+
+****************************************************************************
+* QtQuick *
+****************************************************************************
+
+ - Item Views:
+ * [QTBUG-76487] We now properly populate delegates with the populate
+ transition when the view is resized after componentComplete.
+ * [QTBUG-31677] A ListView footer is now positioned correctly after the
+ last item is removed.
+ * [QTBUG-76433][QTBUG-44308] Fixed a crash while doing fast flicking in
+ transitions that use Animators.
+ * [QTBUG-76254] Fixed a crash in QQmlDelegateModel.
+
+ - Input:
+ * [QTBUG-75399] Fixed a crash when using the KeyNavigation attached property.
+ * [QTBUG-76875] DragHandler now respects acceptedButtons.
+ * [QTBUG-71218] If a Controls 2 Button has a DragHandler, the button is
+ now released when the drag begins.
+
+ - Scene graph:
+ * [QTBUG-76603] qmlscene now sets the default surface format earlier
+ and correctly.
+ * [QTBUG-68566] Fixed rendering freeze when using software rendering
+ of WebEngine in QQuickWidget.
+ * [QTBUG-66810] Software rendering: repaint everything when moving
+ between HiDpi and lower-resolution screens.
+
+ - Text:
+ * [QTBUG-77217] Fixed a bug where aligning an image to "top" or "bottom"
+ could cause a crash under certain circumstances.
+ * [QTBUG-76528] Fixed missing glyphs and in some cases crashes when
+ displaying many characters from the same font on a system with a
+ low maximum texture size.
+ * [QTBUG-76528] Fixed a bug when displaying many characters from the same
+ font on a system with a low maximum texture size.
+ * [QTBUG-74761] Added support for text color when using color fonts.
diff --git a/dist/changes-5.13.1 b/dist/changes-5.13.1
new file mode 100644
index 0000000000..d859a5e747
--- /dev/null
+++ b/dist/changes-5.13.1
@@ -0,0 +1,107 @@
+Qt 5.13.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.13.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.13 series is binary compatible with the 5.12.x series.
+Applications compiled for 5.12 will continue to run with 5.13.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+ - [QTBUG-76871] TapHandler.point now holds the release position while the
+ tapped() signal is emitted.
+ - [QTBUG-14769][QTBUG-50482] TextEdit now uses the I-beam cursor by default,
+ and the pointing cursor for links. But if user code sets a custom cursor,
+ we restore it when the mouse is no longer hovering a link.
+
+****************************************************************************
+* QtQml *
+****************************************************************************
+
+ - [QTBUG-56264] Fixed segfault on Sparc64.
+ - [QTBUG-77102] Fix bug with singletons not being imported from modules when
+ using older versions.
+ - [QTBUG-77047] Fixed crash when creating arrays using the spread operator.
+ - [QTBUG-75983] Fixed crash in XMLHttpRequest.open.
+ - [QTBUG-77012] Fixed static build issue: multiple definitions of
+ qtPositionAttributeName().
+ - [QTBUG-71329] Fixed promise chaining.
+ - [QTBUG-76441] Fix support for import statements using qrc:/ urls.
+ - [QTBUG-55407] Fixed a crash when setData or create is called after a user
+ mistakenly used the internal constructor of QQmlComponent which does
+ not take an engine.
+ - [QTBUG-76796] Fixed late binding re-evaluation when using typeof(name).
+ - [QTBUG-76627] qmlplugindump now finds enums in composite types.
+ - [QTBUG-76656] Fixed resolution of 'this' when using the call operator on scope and context
+ properties.
+ - [QTBUG-71387] Fixed a crash after calling qmlClearTypeRegistrations().
+ - [QTBUG-75642] Fixed an invalid memory read in JIT with template literals.
+ - [QTBUG-75939] Fix crash when destroying QJSValues from other threads.
+ - [QTBUG-76085] Fixed automatic loading of translations from resources.
+ - [QTBUG-76018] Fixed grammar to permit readonly list properties.
+ - [QTBUG-75880] Fix accidental implicit creation of local variable when using anonymous functions
+ in object literals.
+ - [QTBUG-67343] Fixed assertion when having a ShaderEffect as a delegate
+ in a ComboBox.
+ - [QTBUG-75896] Fixed property lookup in QML singletons.
+ - [QTBUG-75392] Fixed a crash by working around a compiler bug.
+ - [QTBUG-48809] Print a warning when using absolute paths in qmldir files.
+ - [QTBUG-75609] Fixed a performance regression with attached properties.
+ - [QTBUG-76074] Loader now frees custom qml types when unloading.
+
+****************************************************************************
+* QtQuick *
+****************************************************************************
+
+ - Item Views:
+ * [QTBUG-76487] We now properly populate delegates with the populate
+ transition when the view is resized after componentComplete.
+ * [QTBUG-31677] A ListView footer is now positioned correctly after the
+ last item is removed.
+ * [QTBUG-76433][QTBUG-44308] Fixed a crash while doing fast flicking in
+ transitions that use Animators.
+ * [QTBUG-76254] Fixed a crash in QQmlDelegateModel.
+ * [QTBUG-71581] Fixed a crash in ListView when closing an application that
+ dynamically creates and appends items to an ObjectModel.
+
+ - Input:
+ * [QTBUG-75399] Fixed a crash when using the KeyNavigation attached property.
+ * [QTBUG-76875] DragHandler now respects acceptedButtons.
+ * [QTBUG-71218] If a Controls 2 Button has a DragHandler, the button is
+ now released when the drag begins.
+ * [QTBUG-75770] MouseArea now respects QPlatformTheme::TouchDoubleTapDistance
+ to avoid generating double-clicks while moving and clicking the mouse quickly.
+
+ - Scene graph:
+ * [QTBUG-76603] qmlscene now sets the default surface format earlier
+ and correctly.
+ * [QTBUG-68566] Fixed rendering freeze when using software rendering
+ of WebEngine in QQuickWidget.
+ * [QTBUG-73768] Fixed an assert in BorderImage when any border size
+ exceeds source image size.
+ * [QTBUG-66810] Software rendering: repaint everything when moving
+ between HiDpi and lower-resolution screens.
+ * [QTBUG-74348] Fixed leaking scene graph rendering contexts when using
+ the threaded render loop.
+ * [QTBUG-76055] Cleaned up error messages in shadereffect.
+
+ - Text:
+ * [QTBUG-74761] Added support for text color when using color fonts.
+ * [QTBUG-76528] Fixed missing glyphs and in some cases crashes when
+ displaying many characters from the same font on a system with a
+ low maximum texture size.
+ * [QTBUG-75002] Accessibility: StaticText nodes are announced as
+ read-only rather than editable in Windows Narrator.
diff --git a/examples/HACKING b/examples/HACKING
deleted file mode 100644
index 7d2a61a481..0000000000
--- a/examples/HACKING
+++ /dev/null
@@ -1,23 +0,0 @@
-Some guidelines for Qt QML examples
-
-Snippets
----
-Snippets are snatches of QML code that won't even run on their own. They don't belong here, they belong in doc/src/snippets. They should be contained in files that will compile on their own, for automated syntax validation, but don't have to look like anything.
-
-Examples
----
-
-Examples are large blocks of QML code that demonstrate a feature. You should be able to launch an example and visually see the feature take effect. Examples should be written in a small form, and should automatically activate any features. Ideally, when you run an example, you see the feature demonstrate itself over and over until you get bored and close the application using your platform's close window mechanism. Examples shouldn't contain their own close buttons or start screen, explanatory text should be kept to a minimum (show, not tell), and reserve interaction for demonstrating interactive elements. The code should be held to a high level of quality, and should be understandable by people new to QML.
-
-Unless the demonstrated feature uses it, assume no interface devices other than a screen that can show a 320x480 rectangle and a generic pointing device (with the shared subset of mouse/touch functionality).
-
-Groups of similar examples should be placed in one folder with a single launcher application, which uses the shared folder of common components.
-
-The example, or launcher application in case of groups, should contain a qdoc comment explaining the example. The example or launcher should be buildable as a full C++ application and runnable with the standard qml file launcher. Usually this will consist primarily of using the macro found in shared.h.
-
-Demos
----
-
-Demos are examples of creating full applications using QML. They should fit both a desktop and a mobile form factor, they should have their own start screen and method of exiting the application. They should be at a level of quality that you'd be comfortable submitting them to an app store for a platform of the appropriate hardware (screen size, input methods, etc.). The code should be written to a level that is easily understood and modified by a QML expert.
-
-Demos should have a qdoc file in their directory explaining the demo at a high level. The demo should be buildable as a full C++ application and preferably runnable with the standard qml file launcher.
diff --git a/examples/qml/doc/src/qml-extending.qdoc b/examples/qml/doc/src/qml-extending.qdoc
index e56dd90dd7..64d7235031 100644
--- a/examples/qml/doc/src/qml-extending.qdoc
+++ b/examples/qml/doc/src/qml-extending.qdoc
@@ -178,12 +178,14 @@ previous example. However, as we have repurposed the People class as a common
base for Boy and Girl, we want to prevent it from being instantiated from QML
directly - an explicit Boy or Girl should be instantiated instead.
-\snippet referenceexamples/coercion/main.cpp 0
+\snippet referenceexamples/coercion/person.h 0
While we want to disallow instantiating Person from within QML, it still needs
to be registered with the QML engine, so that it can be used as a property type
and other types can be coerced to it.
+\snippet referenceexamples/coercion/main.cpp 0
+
\section2 Define Boy and Girl
The implementation of Boy and Girl is trivial.
diff --git a/examples/qml/qmlextensionplugins/plugin.cpp b/examples/qml/qmlextensionplugins/plugin.cpp
index 4866106e4a..a6d1d3ff63 100644
--- a/examples/qml/qmlextensionplugins/plugin.cpp
+++ b/examples/qml/qmlextensionplugins/plugin.cpp
@@ -112,6 +112,7 @@ class TimeModel : public QObject
Q_OBJECT
Q_PROPERTY(int hour READ hour NOTIFY timeChanged)
Q_PROPERTY(int minute READ minute NOTIFY timeChanged)
+ QML_NAMED_ELEMENT(Time)
//![0]
public:
@@ -157,7 +158,7 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(uri == QLatin1String("TimeExample"));
- qmlRegisterType<TimeModel>(uri, 1, 0, "Time");
+ qmlRegisterTypesAndRevisions<TimeModel>(uri, 1);
}
};
//![plugin]
diff --git a/examples/qml/referenceexamples/adding/main.cpp b/examples/qml/referenceexamples/adding/main.cpp
index e312149da1..ffd0e90c42 100644
--- a/examples/qml/referenceexamples/adding/main.cpp
+++ b/examples/qml/referenceexamples/adding/main.cpp
@@ -57,7 +57,7 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
//![0]
- qmlRegisterType<Person>("People", 1,0, "Person");
+ qmlRegisterTypesAndRevisions<Person>("People", 1);
//![0]
QQmlEngine engine;
@@ -70,5 +70,5 @@ int main(int argc, char ** argv)
qWarning() << component.errors();
}
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/examples/qml/referenceexamples/adding/person.h b/examples/qml/referenceexamples/adding/person.h
index f40c8d8086..530c335dee 100644
--- a/examples/qml/referenceexamples/adding/person.h
+++ b/examples/qml/referenceexamples/adding/person.h
@@ -51,12 +51,15 @@
#define PERSON_H
#include <QObject>
+#include <QtQml/qqml.h>
+
//![0]
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+ QML_ELEMENT
public:
Person(QObject *parent = nullptr);
diff --git a/examples/qml/referenceexamples/attached/birthdayparty.h b/examples/qml/referenceexamples/attached/birthdayparty.h
index 15375f14d9..308d0652a8 100644
--- a/examples/qml/referenceexamples/attached/birthdayparty.h
+++ b/examples/qml/referenceexamples/attached/birthdayparty.h
@@ -59,6 +59,7 @@ class BirthdayPartyAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp)
+ QML_ANONYMOUS
public:
BirthdayPartyAttached(QObject *object);
@@ -75,6 +76,12 @@ class BirthdayParty : public QObject
Q_PROPERTY(Person *host READ host WRITE setHost)
Q_PROPERTY(QQmlListProperty<Person> guests READ guests)
Q_CLASSINFO("DefaultProperty", "guests")
+ QML_ELEMENT
+
+//! [declare attached]
+ QML_ATTACHED(BirthdayPartyAttached)
+//! [declare attached]
+
public:
BirthdayParty(QObject *parent = nullptr);
@@ -93,7 +100,4 @@ private:
QList<Person *> m_guests;
};
-//! [declare attached]
-QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
-//! [declare attached]
#endif // BIRTHDAYPARTY_H
diff --git a/examples/qml/referenceexamples/attached/main.cpp b/examples/qml/referenceexamples/attached/main.cpp
index 581b033dfc..ab1c6b9637 100644
--- a/examples/qml/referenceexamples/attached/main.cpp
+++ b/examples/qml/referenceexamples/attached/main.cpp
@@ -58,12 +58,9 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayPartyAttached>();
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<ShoeDescription>();
- qmlRegisterType<Person>();
- qmlRegisterType<Boy>("People", 1,0, "Boy");
- qmlRegisterType<Girl>("People", 1,0, "Girl");
+ qmlRegisterTypesAndRevisions<BirthdayPartyAttached,
+ BirthdayParty, ShoeDescription,
+ Person, Boy, Girl>("People", 1);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
@@ -93,9 +90,9 @@ int main(int argc, char ** argv)
qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString());
}
- } else {
- qWarning() << component.errors();
+ return EXIT_SUCCESS;
}
- return 0;
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/attached/person.h b/examples/qml/referenceexamples/attached/person.h
index 2398da38bf..239f4405c0 100644
--- a/examples/qml/referenceexamples/attached/person.h
+++ b/examples/qml/referenceexamples/attached/person.h
@@ -52,6 +52,7 @@
#include <QObject>
#include <QColor>
+#include <QtQml/qqml.h>
class ShoeDescription : public QObject
{
@@ -60,6 +61,7 @@ class ShoeDescription : public QObject
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(QString brand READ brand WRITE setBrand)
Q_PROPERTY(qreal price READ price WRITE setPrice)
+ QML_ANONYMOUS
public:
ShoeDescription(QObject *parent = 0);
@@ -86,6 +88,7 @@ class Person : public QObject
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(ShoeDescription *shoe READ shoe)
+ QML_ANONYMOUS
public:
Person(QObject *parent = nullptr);
@@ -101,6 +104,7 @@ private:
class Boy : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Boy(QObject * parent = nullptr);
};
@@ -108,6 +112,7 @@ public:
class Girl : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Girl(QObject * parent = nullptr);
};
diff --git a/examples/qml/referenceexamples/binding/birthdayparty.h b/examples/qml/referenceexamples/binding/birthdayparty.h
index 15e1908ece..3cd5cf1c9a 100644
--- a/examples/qml/referenceexamples/binding/birthdayparty.h
+++ b/examples/qml/referenceexamples/binding/birthdayparty.h
@@ -60,6 +60,7 @@ class BirthdayPartyAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp NOTIFY rsvpChanged)
+ QML_ANONYMOUS
public:
BirthdayPartyAttached(QObject *object);
@@ -82,6 +83,8 @@ class BirthdayParty : public QObject
Q_PROPERTY(QQmlListProperty<Person> guests READ guests)
Q_PROPERTY(QString announcement READ announcement WRITE setAnnouncement)
Q_CLASSINFO("DefaultProperty", "guests")
+ QML_ELEMENT
+ QML_ATTACHED(BirthdayPartyAttached)
public:
BirthdayParty(QObject *parent = nullptr);
@@ -107,6 +110,4 @@ private:
QList<Person *> m_guests;
};
-QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
-
#endif // BIRTHDAYPARTY_H
diff --git a/examples/qml/referenceexamples/binding/main.cpp b/examples/qml/referenceexamples/binding/main.cpp
index 99187eba3e..8c6e3222d8 100644
--- a/examples/qml/referenceexamples/binding/main.cpp
+++ b/examples/qml/referenceexamples/binding/main.cpp
@@ -58,13 +58,8 @@
int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayPartyAttached>();
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<HappyBirthdaySong>("People", 1,0, "HappyBirthdaySong");
- qmlRegisterType<ShoeDescription>();
- qmlRegisterType<Person>();
- qmlRegisterType<Boy>("People", 1,0, "Boy");
- qmlRegisterType<Girl>("People", 1,0, "Girl");
+ qmlRegisterTypesAndRevisions<BirthdayPartyAttached, BirthdayParty, HappyBirthdaySong,
+ ShoeDescription, Person, Boy, Girl>("People", 1);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
@@ -94,9 +89,9 @@ int main(int argc, char ** argv)
}
party->startParty();
- } else {
- qWarning() << component.errors();
+ return QCoreApplication::exec();
}
- return app.exec();
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/binding/person.h b/examples/qml/referenceexamples/binding/person.h
index 543b24f971..af9864950a 100644
--- a/examples/qml/referenceexamples/binding/person.h
+++ b/examples/qml/referenceexamples/binding/person.h
@@ -52,6 +52,7 @@
#include <QObject>
#include <QColor>
+#include <QtQml/qqml.h>
class ShoeDescription : public QObject
{
@@ -60,6 +61,7 @@ class ShoeDescription : public QObject
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY shoeChanged)
Q_PROPERTY(QString brand READ brand WRITE setBrand NOTIFY shoeChanged)
Q_PROPERTY(qreal price READ price WRITE setPrice NOTIFY shoeChanged)
+ QML_ANONYMOUS
public:
ShoeDescription(QObject *parent = nullptr);
@@ -91,6 +93,7 @@ class Person : public QObject
// ![0]
Q_PROPERTY(ShoeDescription *shoe READ shoe CONSTANT)
// ![0]
+ QML_ANONYMOUS
public:
Person(QObject *parent = nullptr);
@@ -109,6 +112,7 @@ private:
class Boy : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Boy(QObject * parent = nullptr);
};
@@ -116,6 +120,7 @@ public:
class Girl : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Girl(QObject * parent = nullptr);
};
diff --git a/examples/qml/referenceexamples/coercion/main.cpp b/examples/qml/referenceexamples/coercion/main.cpp
index 262cdf6320..2c2bd92e8d 100644
--- a/examples/qml/referenceexamples/coercion/main.cpp
+++ b/examples/qml/referenceexamples/coercion/main.cpp
@@ -58,16 +58,10 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
//![0]
- qmlRegisterType<Person>();
+ qmlRegisterTypesAndRevisions<BirthdayParty, Person, Boy, Girl>("People", 1);
//![0]
- //![register boy girl]
- qmlRegisterType<Boy>("People", 1,0, "Boy");
- qmlRegisterType<Girl>("People", 1,0, "Girl");
- //![register boy girl]
-
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
auto *party = qobject_cast<BirthdayParty *>(component.create());
@@ -82,9 +76,10 @@ int main(int argc, char ** argv)
for (int ii = 0; ii < party->guestCount(); ++ii)
qWarning() << " " << party->guest(ii)->name();
- } else {
- qWarning() << component.errors();
+
+ return EXIT_SUCCESS;
}
- return 0;
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/coercion/person.h b/examples/qml/referenceexamples/coercion/person.h
index 692cf4eb19..6865e0093a 100644
--- a/examples/qml/referenceexamples/coercion/person.h
+++ b/examples/qml/referenceexamples/coercion/person.h
@@ -51,12 +51,16 @@
#define PERSON_H
#include <QObject>
+#include <QtQml/qqml.h>
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+ //![0]
+ QML_ANONYMOUS
+ //![0]
public:
Person(QObject *parent = nullptr);
@@ -75,6 +79,7 @@ private:
class Boy : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Boy(QObject * parent = nullptr);
};
@@ -83,6 +88,7 @@ public:
class Girl : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Girl(QObject * parent = nullptr);
};
diff --git a/examples/qml/referenceexamples/default/main.cpp b/examples/qml/referenceexamples/default/main.cpp
index 017d6495cd..bbe4a239e2 100644
--- a/examples/qml/referenceexamples/default/main.cpp
+++ b/examples/qml/referenceexamples/default/main.cpp
@@ -58,10 +58,7 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<Person>();
- qmlRegisterType<Boy>("People", 1,0, "Boy");
- qmlRegisterType<Girl>("People", 1,0, "Girl");
+ qmlRegisterTypesAndRevisions<BirthdayParty, Person, Boy, Girl>("People", 1);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
@@ -77,9 +74,10 @@ int main(int argc, char ** argv)
for (int ii = 0; ii < party->guestCount(); ++ii)
qWarning() << " " << party->guest(ii)->name();
- } else {
- qWarning() << component.errors();
+
+ return EXIT_SUCCESS;
}
- return 0;
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/default/person.h b/examples/qml/referenceexamples/default/person.h
index 87f69276bf..361a89c599 100644
--- a/examples/qml/referenceexamples/default/person.h
+++ b/examples/qml/referenceexamples/default/person.h
@@ -51,12 +51,14 @@
#define PERSON_H
#include <QObject>
+#include <QtQml/qqml.h>
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+ QML_ANONYMOUS
public:
Person(QObject *parent = nullptr);
@@ -73,6 +75,7 @@ private:
class Boy : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Boy(QObject * parent = nullptr);
};
@@ -80,6 +83,7 @@ public:
class Girl : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Girl(QObject * parent = nullptr);
};
diff --git a/examples/qml/referenceexamples/extended/main.cpp b/examples/qml/referenceexamples/extended/main.cpp
index f91cec76b1..5f8582d08f 100644
--- a/examples/qml/referenceexamples/extended/main.cpp
+++ b/examples/qml/referenceexamples/extended/main.cpp
@@ -70,9 +70,9 @@ int main(int argc, char ** argv)
if (edit) {
edit->show();
- return app.exec();
- } else {
- qWarning() << component.errors();
- return 0;
+ return QApplication::exec();
}
+
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/grouped/main.cpp b/examples/qml/referenceexamples/grouped/main.cpp
index 14cd64fe68..e233aab5b1 100644
--- a/examples/qml/referenceexamples/grouped/main.cpp
+++ b/examples/qml/referenceexamples/grouped/main.cpp
@@ -58,11 +58,7 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<ShoeDescription>();
- qmlRegisterType<Person>();
- qmlRegisterType<Boy>("People", 1,0, "Boy");
- qmlRegisterType<Girl>("People", 1,0, "Girl");
+ qmlRegisterTypesAndRevisions<BirthdayParty, ShoeDescription, Person, Boy, Girl>("People", 1);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
@@ -87,9 +83,9 @@ int main(int argc, char ** argv)
if (bestShoe)
qWarning() << bestShoe->name() << "is wearing the best shoes!";
- } else {
- qWarning() << component.errors();
+ return EXIT_SUCCESS;
}
- return 0;
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/grouped/person.h b/examples/qml/referenceexamples/grouped/person.h
index 6f6caaee7c..df507c7386 100644
--- a/examples/qml/referenceexamples/grouped/person.h
+++ b/examples/qml/referenceexamples/grouped/person.h
@@ -52,6 +52,7 @@
#include <QObject>
#include <QColor>
+#include <QtQml/qqml.h>
class ShoeDescription : public QObject
{
@@ -60,6 +61,7 @@ class ShoeDescription : public QObject
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(QString brand READ brand WRITE setBrand)
Q_PROPERTY(qreal price READ price WRITE setPrice)
+ QML_ANONYMOUS
public:
ShoeDescription(QObject *parent = nullptr);
@@ -88,6 +90,7 @@ class Person : public QObject
// ![1]
Q_PROPERTY(ShoeDescription *shoe READ shoe)
// ![1]
+ QML_ANONYMOUS
public:
Person(QObject *parent = nullptr);
@@ -103,6 +106,7 @@ private:
class Boy : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Boy(QObject * parent = nullptr);
};
@@ -110,6 +114,7 @@ public:
class Girl : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Girl(QObject * parent = nullptr);
};
diff --git a/examples/qml/referenceexamples/methods/main.cpp b/examples/qml/referenceexamples/methods/main.cpp
index 89404ec822..4dd616f8cd 100644
--- a/examples/qml/referenceexamples/methods/main.cpp
+++ b/examples/qml/referenceexamples/methods/main.cpp
@@ -58,8 +58,7 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<Person>("People", 1,0, "Person");
+ qmlRegisterTypesAndRevisions<BirthdayParty, Person>("People", 1);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
@@ -70,9 +69,9 @@ int main(int argc, char ** argv)
qWarning() << "They are inviting:";
for (int ii = 0; ii < party->guestCount(); ++ii)
qWarning() << " " << party->guest(ii)->name();
- } else {
- qWarning() << component.errors();
+ return EXIT_SUCCESS;
}
- return 0;
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/methods/person.h b/examples/qml/referenceexamples/methods/person.h
index 749109dc72..2407fbb1b9 100644
--- a/examples/qml/referenceexamples/methods/person.h
+++ b/examples/qml/referenceexamples/methods/person.h
@@ -51,12 +51,14 @@
#define PERSON_H
#include <QObject>
+#include <QtQml/qqml.h>
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+ QML_ELEMENT
public:
Person(QObject *parent = nullptr);
diff --git a/examples/qml/referenceexamples/properties/main.cpp b/examples/qml/referenceexamples/properties/main.cpp
index a0a2335034..216869bf6c 100644
--- a/examples/qml/referenceexamples/properties/main.cpp
+++ b/examples/qml/referenceexamples/properties/main.cpp
@@ -59,8 +59,7 @@ int main(int argc, char ** argv)
QCoreApplication app(argc, argv);
//![register list]
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<Person>("People", 1,0, "Person");
+ qmlRegisterTypesAndRevisions<BirthdayParty, Person>("People", 1);
//![register list]
QQmlEngine engine;
@@ -72,9 +71,9 @@ int main(int argc, char ** argv)
qWarning() << "They are inviting:";
for (int ii = 0; ii < party->guestCount(); ++ii)
qWarning() << " " << party->guest(ii)->name();
- } else {
- qWarning() << component.errors();
+ return EXIT_SUCCESS;
}
- return 0;
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/properties/person.h b/examples/qml/referenceexamples/properties/person.h
index 749109dc72..2407fbb1b9 100644
--- a/examples/qml/referenceexamples/properties/person.h
+++ b/examples/qml/referenceexamples/properties/person.h
@@ -51,12 +51,14 @@
#define PERSON_H
#include <QObject>
+#include <QtQml/qqml.h>
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+ QML_ELEMENT
public:
Person(QObject *parent = nullptr);
diff --git a/examples/qml/referenceexamples/signal/birthdayparty.h b/examples/qml/referenceexamples/signal/birthdayparty.h
index 9aecc8929c..c815518291 100644
--- a/examples/qml/referenceexamples/signal/birthdayparty.h
+++ b/examples/qml/referenceexamples/signal/birthdayparty.h
@@ -59,6 +59,7 @@ class BirthdayPartyAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp)
+ QML_ANONYMOUS
public:
BirthdayPartyAttached(QObject *object);
@@ -75,6 +76,8 @@ class BirthdayParty : public QObject
Q_PROPERTY(Person *host READ host WRITE setHost)
Q_PROPERTY(QQmlListProperty<Person> guests READ guests)
Q_CLASSINFO("DefaultProperty", "guests")
+ QML_ELEMENT
+ QML_ATTACHED(BirthdayPartyAttached)
public:
BirthdayParty(QObject *parent = nullptr);
@@ -97,6 +100,5 @@ private:
Person *m_host;
QList<Person *> m_guests;
};
-QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
#endif // BIRTHDAYPARTY_H
diff --git a/examples/qml/referenceexamples/signal/main.cpp b/examples/qml/referenceexamples/signal/main.cpp
index bb75e02bc2..f431e2bdc8 100644
--- a/examples/qml/referenceexamples/signal/main.cpp
+++ b/examples/qml/referenceexamples/signal/main.cpp
@@ -58,12 +58,8 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayPartyAttached>();
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<ShoeDescription>();
- qmlRegisterType<Person>();
- qmlRegisterType<Boy>("People", 1,0, "Boy");
- qmlRegisterType<Girl>("People", 1,0, "Girl");
+ qmlRegisterTypesAndRevisions<BirthdayPartyAttached, BirthdayParty, ShoeDescription,
+ Person, Boy, Girl>("People", 1);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
@@ -93,9 +89,9 @@ int main(int argc, char ** argv)
}
party->startParty();
- } else {
- qWarning() << component.errors();
+ return EXIT_SUCCESS;
}
- return 0;
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/signal/person.h b/examples/qml/referenceexamples/signal/person.h
index 06d4f2eb27..7283f39f61 100644
--- a/examples/qml/referenceexamples/signal/person.h
+++ b/examples/qml/referenceexamples/signal/person.h
@@ -52,6 +52,7 @@
#include <QObject>
#include <QColor>
+#include <QtQml/qqml.h>
class ShoeDescription : public QObject
{
@@ -60,6 +61,7 @@ class ShoeDescription : public QObject
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(QString brand READ brand WRITE setBrand)
Q_PROPERTY(qreal price READ price WRITE setPrice)
+ QML_ANONYMOUS
public:
ShoeDescription(QObject *parent = nullptr);
@@ -86,6 +88,7 @@ class Person : public QObject
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(ShoeDescription *shoe READ shoe)
+ QML_ANONYMOUS
public:
Person(QObject *parent = nullptr);
@@ -101,6 +104,7 @@ private:
class Boy : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Boy(QObject * parent = nullptr);
};
@@ -108,6 +112,7 @@ public:
class Girl : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Girl(QObject * parent = nullptr);
};
diff --git a/examples/qml/referenceexamples/valuesource/birthdayparty.h b/examples/qml/referenceexamples/valuesource/birthdayparty.h
index 18a9b96147..25e2342937 100644
--- a/examples/qml/referenceexamples/valuesource/birthdayparty.h
+++ b/examples/qml/referenceexamples/valuesource/birthdayparty.h
@@ -60,6 +60,7 @@ class BirthdayPartyAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp)
+ QML_ANONYMOUS
public:
BirthdayPartyAttached(QObject *object);
@@ -79,6 +80,8 @@ class BirthdayParty : public QObject
Q_PROPERTY(QString announcement READ announcement WRITE setAnnouncement)
// ![0]
Q_CLASSINFO("DefaultProperty", "guests")
+ QML_ELEMENT
+ QML_ATTACHED(BirthdayPartyAttached)
public:
BirthdayParty(QObject *parent = nullptr);
@@ -102,6 +105,5 @@ private:
Person *m_host;
QList<Person *> m_guests;
};
-QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
#endif // BIRTHDAYPARTY_H
diff --git a/examples/qml/referenceexamples/valuesource/main.cpp b/examples/qml/referenceexamples/valuesource/main.cpp
index 4bef695fe2..72e75fdea1 100644
--- a/examples/qml/referenceexamples/valuesource/main.cpp
+++ b/examples/qml/referenceexamples/valuesource/main.cpp
@@ -59,13 +59,8 @@ int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
- qmlRegisterType<BirthdayPartyAttached>();
- qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty");
- qmlRegisterType<HappyBirthdaySong>("People", 1,0, "HappyBirthdaySong");
- qmlRegisterType<ShoeDescription>();
- qmlRegisterType<Person>();
- qmlRegisterType<Boy>("People", 1,0, "Boy");
- qmlRegisterType<Girl>("People", 1,0, "Girl");
+ qmlRegisterTypesAndRevisions<BirthdayPartyAttached, BirthdayParty, HappyBirthdaySong,
+ ShoeDescription, Person, Boy, Girl>("People", 1);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
@@ -95,9 +90,9 @@ int main(int argc, char ** argv)
}
party->startParty();
- } else {
- qWarning() << component.errors();
+ return QCoreApplication::exec();
}
- return app.exec();
+ qWarning() << component.errors();
+ return EXIT_FAILURE;
}
diff --git a/examples/qml/referenceexamples/valuesource/person.h b/examples/qml/referenceexamples/valuesource/person.h
index 06d4f2eb27..7283f39f61 100644
--- a/examples/qml/referenceexamples/valuesource/person.h
+++ b/examples/qml/referenceexamples/valuesource/person.h
@@ -52,6 +52,7 @@
#include <QObject>
#include <QColor>
+#include <QtQml/qqml.h>
class ShoeDescription : public QObject
{
@@ -60,6 +61,7 @@ class ShoeDescription : public QObject
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(QString brand READ brand WRITE setBrand)
Q_PROPERTY(qreal price READ price WRITE setPrice)
+ QML_ANONYMOUS
public:
ShoeDescription(QObject *parent = nullptr);
@@ -86,6 +88,7 @@ class Person : public QObject
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(ShoeDescription *shoe READ shoe)
+ QML_ANONYMOUS
public:
Person(QObject *parent = nullptr);
@@ -101,6 +104,7 @@ private:
class Boy : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Boy(QObject * parent = nullptr);
};
@@ -108,6 +112,7 @@ public:
class Girl : public Person
{
Q_OBJECT
+ QML_ELEMENT
public:
Girl(QObject * parent = nullptr);
};
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp b/examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp
index fbff60c0e6..af50cc14f2 100644
--- a/examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp
@@ -56,7 +56,7 @@ int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
- qmlRegisterType<PieChart>("Charts", 1, 0, "PieChart");
+ qmlRegisterTypesAndRevisions<PieChart>("Charts", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h b/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h
index 005a706db6..687f8e2b4d 100644
--- a/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h
@@ -59,6 +59,7 @@ class PieChart : public QQuickPaintedItem
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QColor color READ color WRITE setColor)
+ QML_ELEMENT
public:
PieChart(QQuickItem *parent = 0);
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp b/examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp
index fbff60c0e6..af50cc14f2 100644
--- a/examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp
@@ -56,7 +56,7 @@ int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
- qmlRegisterType<PieChart>("Charts", 1, 0, "PieChart");
+ qmlRegisterTypesAndRevisions<PieChart>("Charts", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h b/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h
index 36bfa3ada0..271afbf653 100644
--- a/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h
@@ -60,7 +60,7 @@ class PieChart : public QQuickPaintedItem
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QColor color READ color WRITE setColor)
-
+ QML_ELEMENT
//![1]
public:
//![1]
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp b/examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp
index fbff60c0e6..af50cc14f2 100644
--- a/examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp
@@ -56,7 +56,7 @@ int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
- qmlRegisterType<PieChart>("Charts", 1, 0, "PieChart");
+ qmlRegisterTypesAndRevisions<PieChart>("Charts", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h b/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h
index 9de2baa82e..58b1339298 100644
--- a/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h
@@ -59,6 +59,7 @@ class PieChart : public QQuickPaintedItem
//![0]
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
+ QML_ELEMENT
//![1]
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp
index 82355d0438..7c5d1a6885 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp
@@ -59,10 +59,8 @@ int main(int argc, char *argv[])
//![0]
QGuiApplication app(argc, argv);
- qmlRegisterType<PieChart>("Charts", 1, 0, "PieChart");
-
//![1]
- qmlRegisterType<PieSlice>("Charts", 1, 0, "PieSlice");
+ qmlRegisterTypesAndRevisions<PieChart, PieSlice>("Charts", 1);
//![1]
QQuickView view;
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h
index 6cd09a9293..b762ce1c49 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h
@@ -61,7 +61,7 @@ class PieChart : public QQuickItem
Q_PROPERTY(PieSlice* pieSlice READ pieSlice WRITE setPieSlice)
//![0]
Q_PROPERTY(QString name READ name WRITE setName)
-
+ QML_ELEMENT
//![1]
public:
//![1]
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h
index 10ab4d34b6..6e64917851 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h
@@ -58,6 +58,7 @@ class PieSlice : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor)
+ QML_ELEMENT
public:
PieSlice(QQuickItem *parent = 0);
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp
index 8aa6fef018..70ef103e4d 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp
@@ -57,8 +57,7 @@ int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
- qmlRegisterType<PieChart>("Charts", 1, 0, "PieChart");
- qmlRegisterType<PieSlice>("Charts", 1, 0, "PieSlice");
+ qmlRegisterTypesAndRevisions<PieChart, PieSlice>("Charts", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h
index 9b3390b902..236fa6796f 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h
@@ -61,6 +61,7 @@ class PieChart : public QQuickItem
Q_PROPERTY(QQmlListProperty<PieSlice> slices READ slices)
//![0]
Q_PROPERTY(QString name READ name WRITE setName)
+ QML_ELEMENT
//![1]
public:
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h
index f8f7f7c36a..0b290851f0 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h
@@ -60,6 +60,7 @@ class PieSlice : public QQuickPaintedItem
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(int fromAngle READ fromAngle WRITE setFromAngle)
Q_PROPERTY(int angleSpan READ angleSpan WRITE setAngleSpan)
+ QML_ELEMENT
//![0]
public:
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp
index ce8b95b6b6..74d382ec57 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp
@@ -55,8 +55,7 @@
void ChartsPlugin::registerTypes(const char *uri)
{
- qmlRegisterType<PieChart>(uri, 1, 0, "PieChart");
- qmlRegisterType<PieSlice>(uri, 1, 0, "PieSlice");
+ qmlRegisterTypesAndRevisions<PieChart, PieSlice>(uri, 1);
}
//![0]
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h
index cd67bdf34a..e6b768b274 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h
@@ -59,6 +59,7 @@ class PieChart : public QQuickItem
Q_OBJECT
Q_PROPERTY(QQmlListProperty<PieSlice> slices READ slices)
Q_PROPERTY(QString name READ name WRITE setName)
+ QML_ELEMENT
public:
PieChart(QQuickItem *parent = 0);
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h
index 71cc20a369..091870bd51 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h
@@ -59,6 +59,7 @@ class PieSlice : public QQuickPaintedItem
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(int fromAngle READ fromAngle WRITE setFromAngle)
Q_PROPERTY(int angleSpan READ angleSpan WRITE setAngleSpan)
+ QML_ELEMENT
public:
PieSlice(QQuickItem *parent = 0);
diff --git a/examples/quick/customitems/maskedmousearea/main.cpp b/examples/quick/customitems/maskedmousearea/main.cpp
index 63558d1b20..626f0fd765 100644
--- a/examples/quick/customitems/maskedmousearea/main.cpp
+++ b/examples/quick/customitems/maskedmousearea/main.cpp
@@ -59,7 +59,7 @@ int main(int argc, char* argv[])
QGuiApplication app(argc,argv);
QQuickView view;
- qmlRegisterType<MaskedMouseArea>("Example", 1, 0, "MaskedMouseArea");
+ qmlRegisterTypesAndRevisions<MaskedMouseArea>("Example", 1);
view.setSource(QUrl("qrc:///customitems/maskedmousearea/maskedmousearea.qml"));
view.show();
diff --git a/examples/quick/customitems/maskedmousearea/maskedmousearea.h b/examples/quick/customitems/maskedmousearea/maskedmousearea.h
index 28ff6ca9df..39d78a019a 100644
--- a/examples/quick/customitems/maskedmousearea/maskedmousearea.h
+++ b/examples/quick/customitems/maskedmousearea/maskedmousearea.h
@@ -62,6 +62,7 @@ class MaskedMouseArea : public QQuickItem
Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
Q_PROPERTY(QUrl maskSource READ maskSource WRITE setMaskSource NOTIFY maskSourceChanged)
Q_PROPERTY(qreal alphaThreshold READ alphaThreshold WRITE setAlphaThreshold NOTIFY alphaThresholdChanged)
+ QML_ELEMENT
public:
MaskedMouseArea(QQuickItem *parent = 0);
diff --git a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h
index d3a1f4ba91..41750d1647 100644
--- a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h
+++ b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h
@@ -59,6 +59,6 @@ class TextBalloonPlugin : public QQmlExtensionPlugin
public:
void registerTypes(const char *uri)
{
- qmlRegisterType<TextBalloon>(uri, 1, 0, "TextBalloon");
+ qmlRegisterTypesAndRevisions<TextBalloon>(uri, 1);
}
};
diff --git a/examples/quick/customitems/painteditem/textballoon.h b/examples/quick/customitems/painteditem/textballoon.h
index 81b3e2961d..eb72804602 100644
--- a/examples/quick/customitems/painteditem/textballoon.h
+++ b/examples/quick/customitems/painteditem/textballoon.h
@@ -58,6 +58,7 @@ class TextBalloon : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(bool rightAligned READ isRightAligned WRITE setRightAligned NOTIFY rightAlignedChanged)
+ QML_ELEMENT
public:
TextBalloon(QQuickItem *parent = 0);
diff --git a/examples/quick/imageelements/doc/src/imageelements.qdoc b/examples/quick/imageelements/doc/src/imageelements.qdoc
index 2c6490fb2c..4c00915e56 100644
--- a/examples/quick/imageelements/doc/src/imageelements.qdoc
+++ b/examples/quick/imageelements/doc/src/imageelements.qdoc
@@ -38,12 +38,12 @@
\section1 Scaling with BorderImage
- \e BorderImage shows off the various scaling modes of the \l BorderImage
+ \e BorderImage shows the various scaling modes of the \l BorderImage
type by setting its horizontalTileMode and verticalTileMode properties.
\section1 Image Fill
- \e Image shows off the various fill modes of the \l Image type.
+ \e Image shows the various fill modes of the \l Image type.
\section1 Shadow Effects
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h b/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h
index 3a4c5a13c2..6270e7adff 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h
+++ b/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h
@@ -111,6 +111,7 @@ class FbItem : public QQuickFramebufferObject
Q_PROPERTY(QVector3D target READ target WRITE setTarget)
Q_PROPERTY(QVector3D rotation READ rotation WRITE setRotation)
Q_PROPERTY(bool multisample READ multisample WRITE setMultisample)
+ QML_ELEMENT
public:
explicit FbItem(QQuickItem *parent = 0);
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp b/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp
index 84e116dce6..6ebf36c454 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp
+++ b/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp
@@ -86,7 +86,7 @@ MainWindow::MainWindow(bool transparency, bool noRenderAlpha)
m_labelStatus = new QLabel;
layout->addWidget(m_labelStatus);
- qmlRegisterType<FbItem>("fbitem", 1, 0, "FbItem");
+ qmlRegisterTypesAndRevisions<FbItem>("fbitem", 1);
QWidget *quickContainer = new QWidget;
layout->addWidget(quickContainer);
diff --git a/examples/quick/quickwidgets/quickwidget/fbitem.h b/examples/quick/quickwidgets/quickwidget/fbitem.h
index 7beb9874a5..c1fb866c9a 100644
--- a/examples/quick/quickwidgets/quickwidget/fbitem.h
+++ b/examples/quick/quickwidgets/quickwidget/fbitem.h
@@ -56,6 +56,7 @@
class FbItem : public QQuickFramebufferObject
{
Q_OBJECT
+ QML_ELEMENT
public:
Renderer *createRenderer() const;
};
diff --git a/examples/quick/quickwidgets/quickwidget/main.cpp b/examples/quick/quickwidgets/quickwidget/main.cpp
index c54586c5de..541f543f07 100644
--- a/examples/quick/quickwidgets/quickwidget/main.cpp
+++ b/examples/quick/quickwidgets/quickwidget/main.cpp
@@ -214,7 +214,7 @@ int main(int argc, char **argv)
optMultipleSample = parser.isSet(multipleSampleOption);
optCoreProfile = parser.isSet(coreProfileOption);
- qmlRegisterType<FbItem>("QuickWidgetExample", 1, 0, "FbItem");
+ qmlRegisterTypesAndRevisions<FbItem>("QuickWidgetExample", 1);
MainWindow mainWindow;
mainWindow.show();
diff --git a/examples/quick/scenegraph/customgeometry/beziercurve.h b/examples/quick/scenegraph/customgeometry/beziercurve.h
index f2f7832e6d..be9e4ef49f 100644
--- a/examples/quick/scenegraph/customgeometry/beziercurve.h
+++ b/examples/quick/scenegraph/customgeometry/beziercurve.h
@@ -64,6 +64,7 @@ class BezierCurve : public QQuickItem
Q_PROPERTY(QPointF p4 READ p4 WRITE setP4 NOTIFY p4Changed)
Q_PROPERTY(int segmentCount READ segmentCount WRITE setSegmentCount NOTIFY segmentCountChanged)
+ QML_ELEMENT
public:
BezierCurve(QQuickItem *parent = 0);
diff --git a/examples/quick/scenegraph/customgeometry/main.cpp b/examples/quick/scenegraph/customgeometry/main.cpp
index 6f3c24e87b..9352e4bd24 100644
--- a/examples/quick/scenegraph/customgeometry/main.cpp
+++ b/examples/quick/scenegraph/customgeometry/main.cpp
@@ -58,7 +58,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<BezierCurve>("CustomGeometry", 1, 0, "BezierCurve");
+ qmlRegisterTypesAndRevisions<BezierCurve>("CustomGeometry", 1);
QQuickView view;
QSurfaceFormat format = view.format();
diff --git a/examples/quick/scenegraph/d3d11underqml/d3d11squircle.h b/examples/quick/scenegraph/d3d11underqml/d3d11squircle.h
index be9aadc43b..4be3671d1c 100644
--- a/examples/quick/scenegraph/d3d11underqml/d3d11squircle.h
+++ b/examples/quick/scenegraph/d3d11underqml/d3d11squircle.h
@@ -59,6 +59,7 @@ class D3D11Squircle : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
+ QML_ELEMENT
public:
D3D11Squircle();
diff --git a/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro b/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro
index 3c94d48ac4..7658a9a813 100644
--- a/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro
+++ b/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro
@@ -1,3 +1,5 @@
+!win32: error("This example requires Windows")
+
QT += qml quick
HEADERS += d3d11squircle.h
diff --git a/examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc b/examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc
index d7b60d3b81..1f0c15e1c6 100644
--- a/examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc
+++ b/examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc
@@ -51,8 +51,8 @@
program that draws the squircles.
The example is equivalent in most ways to the \l{Scene Graph - OpenGL Under
- QML}{OpenGL Under QML} and \l{Scene Graph - Metal Under QML}{Metal Under
- QML} examples, they all render the same custom content, just via different
- native APIs.
+ QML}{OpenGL Under QML}, \l{Scene Graph - Metal Under QML}{Metal Under QML},
+ and \l{Scene Graph - Vulkan Under QML}{Vulkan Under QML} examples, they all
+ render the same custom content, just via different native APIs.
*/
diff --git a/examples/quick/scenegraph/d3d11underqml/main.cpp b/examples/quick/scenegraph/d3d11underqml/main.cpp
index d26de1144a..dcab8c879c 100644
--- a/examples/quick/scenegraph/d3d11underqml/main.cpp
+++ b/examples/quick/scenegraph/d3d11underqml/main.cpp
@@ -56,7 +56,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<D3D11Squircle>("D3D11UnderQML", 1, 0, "D3D11Squircle");
+ qmlRegisterTypesAndRevisions<D3D11Squircle>("D3D11UnderQML", 1);
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Direct3D11Rhi);
diff --git a/examples/quick/scenegraph/textureinsgnode/CMakeLists.txt b/examples/quick/scenegraph/fboitem/CMakeLists.txt
index 1117ef22a9..1117ef22a9 100644
--- a/examples/quick/scenegraph/textureinsgnode/CMakeLists.txt
+++ b/examples/quick/scenegraph/fboitem/CMakeLists.txt
diff --git a/examples/quick/scenegraph/textureinsgnode/doc/images/textureinsgnode-example.jpg b/examples/quick/scenegraph/fboitem/doc/images/fboitem-example.jpg
index 306b8bab20..306b8bab20 100644
--- a/examples/quick/scenegraph/textureinsgnode/doc/images/textureinsgnode-example.jpg
+++ b/examples/quick/scenegraph/fboitem/doc/images/fboitem-example.jpg
Binary files differ
diff --git a/examples/quick/scenegraph/textureinsgnode/doc/src/textureinsgnode.qdoc b/examples/quick/scenegraph/fboitem/doc/src/fboitem.qdoc
index c1c830338b..b5add02991 100644
--- a/examples/quick/scenegraph/textureinsgnode/doc/src/textureinsgnode.qdoc
+++ b/examples/quick/scenegraph/fboitem/doc/src/fboitem.qdoc
@@ -26,11 +26,11 @@
****************************************************************************/
/*!
- \example scenegraph/textureinsgnode
+ \example scenegraph/fboitem
\title Scene Graph - Rendering FBOs
\ingroup qtquickexamples
\brief Shows how to use FramebufferObjects with Qt Quick.
- \image textureinsgnode-example.jpg
+ \image fboitem-example.jpg
*/
diff --git a/examples/quick/scenegraph/textureinsgnode/fboinsgrenderer.cpp b/examples/quick/scenegraph/fboitem/fboinsgrenderer.cpp
index 8ba5bddb2a..8ba5bddb2a 100644
--- a/examples/quick/scenegraph/textureinsgnode/fboinsgrenderer.cpp
+++ b/examples/quick/scenegraph/fboitem/fboinsgrenderer.cpp
diff --git a/examples/quick/scenegraph/textureinsgnode/fboinsgrenderer.h b/examples/quick/scenegraph/fboitem/fboinsgrenderer.h
index e1a9ce22c8..1b92b56851 100644
--- a/examples/quick/scenegraph/textureinsgnode/fboinsgrenderer.h
+++ b/examples/quick/scenegraph/fboitem/fboinsgrenderer.h
@@ -58,6 +58,7 @@ class LogoRenderer;
class FboInSGRenderer : public QQuickFramebufferObject
{
Q_OBJECT
+ QML_NAMED_ELEMENT(Renderer)
public:
Renderer *createRenderer() const;
};
diff --git a/examples/quick/scenegraph/textureinsgnode/textureinsgnode.pro b/examples/quick/scenegraph/fboitem/fboitem.pro
index 238e20a553..e40e5f4cf8 100644
--- a/examples/quick/scenegraph/textureinsgnode/textureinsgnode.pro
+++ b/examples/quick/scenegraph/fboitem/fboitem.pro
@@ -7,9 +7,9 @@ INCLUDEPATH += ../shared
HEADERS += ../shared/logorenderer.h
SOURCES += ../shared/logorenderer.cpp
-RESOURCES += textureinsgnode.qrc
+RESOURCES += fboitem.qrc
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/textureinsgnode
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/fboitem
INSTALLS += target
OTHER_FILES += \
diff --git a/examples/quick/scenegraph/textureinsgnode/textureinsgnode.qrc b/examples/quick/scenegraph/fboitem/fboitem.qrc
index 9ecf0ada1c..9d9db70654 100644
--- a/examples/quick/scenegraph/textureinsgnode/textureinsgnode.qrc
+++ b/examples/quick/scenegraph/fboitem/fboitem.qrc
@@ -1,5 +1,5 @@
<RCC>
- <qresource prefix="/scenegraph/textureinsgnode">
+ <qresource prefix="/scenegraph/fboitem">
<file>main.qml</file>
</qresource>
</RCC>
diff --git a/examples/quick/scenegraph/textureinsgnode/main.cpp b/examples/quick/scenegraph/fboitem/main.cpp
index 8eececc0aa..056bf24ade 100644
--- a/examples/quick/scenegraph/textureinsgnode/main.cpp
+++ b/examples/quick/scenegraph/fboitem/main.cpp
@@ -58,11 +58,11 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<FboInSGRenderer>("SceneGraphRendering", 1, 0, "Renderer");
+ qmlRegisterTypesAndRevisions<FboInSGRenderer>("SceneGraphRendering", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
- view.setSource(QUrl("qrc:///scenegraph/textureinsgnode/main.qml"));
+ view.setSource(QUrl("qrc:///scenegraph/fboitem/main.qml"));
view.show();
return app.exec();
diff --git a/examples/quick/scenegraph/textureinsgnode/main.qml b/examples/quick/scenegraph/fboitem/main.qml
index 92fa99e847..92fa99e847 100644
--- a/examples/quick/scenegraph/textureinsgnode/main.qml
+++ b/examples/quick/scenegraph/fboitem/main.qml
diff --git a/examples/quick/scenegraph/graph/graph.h b/examples/quick/scenegraph/graph/graph.h
index a1a00cb6dc..e32e657e0e 100644
--- a/examples/quick/scenegraph/graph/graph.h
+++ b/examples/quick/scenegraph/graph/graph.h
@@ -56,6 +56,7 @@
class Graph : public QQuickItem
{
Q_OBJECT
+ QML_ELEMENT
public:
Graph();
diff --git a/examples/quick/scenegraph/graph/main.cpp b/examples/quick/scenegraph/graph/main.cpp
index 2406457ab5..9a575944b9 100644
--- a/examples/quick/scenegraph/graph/main.cpp
+++ b/examples/quick/scenegraph/graph/main.cpp
@@ -58,7 +58,7 @@ int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
- qmlRegisterType<Graph>("Graph", 1, 0, "Graph");
+ qmlRegisterTypesAndRevisions<Graph>("Graph", 1);
QQuickView view;
view.resize(800, 400);
diff --git a/examples/quick/scenegraph/metaltextureimport/doc/images/metaltextureimport-example.jpg b/examples/quick/scenegraph/metaltextureimport/doc/images/metaltextureimport-example.jpg
new file mode 100644
index 0000000000..19ad40cd85
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/doc/images/metaltextureimport-example.jpg
Binary files differ
diff --git a/examples/quick/scenegraph/metaltextureimport/doc/src/metaltextureimport.qdoc b/examples/quick/scenegraph/metaltextureimport/doc/src/metaltextureimport.qdoc
new file mode 100644
index 0000000000..2a584c26cc
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/doc/src/metaltextureimport.qdoc
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example scenegraph/metaltextureimport
+ \title Scene Graph - Metal Texture Import
+ \ingroup qtquickexamples
+ \brief Shows how to use a texture created directly with Metal
+
+ \image metaltextureimport-example.jpg
+
+ The Metal Texture Import example shows how an application can import and
+ use a
+ \l{https://developer.apple.com/documentation/metal/mtltexture}{MTLTexture}
+ in the Qt Quick scene. This provides an alternative to the \l{Scene Graph -
+ Metal Under QML}{underlay}, overlay, or \l{Scene Graph - Custom Rendering
+ with QSGRenderNode}{render node} approaches when it comes to integrating
+ native Metal rendering. In many cases going through a texture, and
+ therefore "flattening" the 3D contents first, is the best option to
+ integrate and mix custom 3D contents with the 2D UI elements provided by Qt
+ Quick.
+
+ \snippet scenegraph/metaltextureimport/main.qml 1
+ \snippet scenegraph/metaltextureimport/main.qml 2
+
+ The application exposes a custom QQuickItem subclass under ther name of
+ CustomTextureItem. This is instantiated in QML. The value of the \c t
+ property is animated as well.
+
+ \snippet scenegraph/metaltextureimport/metaltextureimport.h 1
+
+ The implementation of our custom item involves overriding
+ QQuickItem::updatePaintNode(), as well as functions and slots related to
+ geometry changes and cleanup.
+
+ \snippet scenegraph/metaltextureimport/metaltextureimport.mm 1
+
+ We also need a scenegraph node. Instead of deriving directly from QSGNode,
+ we can use QSGSimpleTextureNode which gives us some of the functionality
+ pre-implemented as a convenience.
+
+ \snippet scenegraph/metaltextureimport/metaltextureimport.mm 2
+
+ The updatePaintNode() function of the item is called on the render thread
+ (if there is one), with the main (gui) thread blocked. Here we create a new
+ node if there has not yet been one, and update it. Accessing Qt objects
+ living on the main thread is safe here, so sync() will calculate and copy
+ the values it needs from QQuickItem or QQuickWindow.
+
+ \snippet scenegraph/metaltextureimport/metaltextureimport.mm 3
+
+ The node does not merely rely on the typical QQuickItem - QSGNode
+ update sequence, it connects to QQuickWindow::beforeRendering() as
+ well. That is where the contents of the Metal texture will be updated by
+ encoding a full render pass, targeting the texture, on the Qt Quicks
+ scenegraph's command buffer. beforeRendering() is the right place for this,
+ because the signal is emitted before Qt Quick starts to encode its own
+ rendering commands. Choosing QQuickWindow::beforeRenderPassRecording()
+ instead would be an error in this exanple.
+
+ \snippet scenegraph/metaltextureimport/metaltextureimport.mm 4
+ \snippet scenegraph/metaltextureimport/metaltextureimport.mm 5
+
+ After copying the values we need, sync() also performs some graphics
+ resource initialization. The MTLDevice is queried from the scenegraph. Once
+ a MTLTexture is available, a QSGTexture wrapping (not owning) it is created
+ via QQuickWindow::createTextureFromNativeObject(). This function is a
+ modern equivalent to QQuickWindow::createTextureFromId() that is not tied
+ to OpenGL. Finally, the QSGTexture is associated with the underlying
+ materials by calling the base class' setTexture() function.
+
+ \snippet scenegraph/metaltextureimport/metaltextureimport.mm 6
+
+ render(), the slot connected to beforeRendering(), encodes the rendering
+ commands using the buffers and pipeline state objects created in sync().
+
+ */
diff --git a/examples/quick/scenegraph/metaltextureimport/main.cpp b/examples/quick/scenegraph/metaltextureimport/main.cpp
new file mode 100644
index 0000000000..c969817e8f
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QtQuick/QQuickView>
+#include "metaltextureimport.h"
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<CustomTextureItem>("MetalTextureImport", 1, 0, "CustomTextureItem");
+
+ QQuickWindow::setSceneGraphBackend(QSGRendererInterface::MetalRhi);
+
+ QQuickView view;
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:///scenegraph/metaltextureimport/main.qml"));
+ view.resize(400, 400);
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/quick/scenegraph/metaltextureimport/main.qml b/examples/quick/scenegraph/metaltextureimport/main.qml
new file mode 100644
index 0000000000..facab4e440
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/main.qml
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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
+//! [1]
+import MetalTextureImport 1.0
+//! [1]
+
+Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+
+ //! [2]
+ CustomTextureItem {
+ id: renderer
+ anchors.fill: parent
+ anchors.margins: 10
+
+ SequentialAnimation on t {
+ NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
+ NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
+ loops: Animation.Infinite
+ running: true
+ }
+ //! [2]
+
+ transform: [
+ Rotation { id: rotation; axis.x: 0; axis.z: 0; axis.y: 1; angle: 0; origin.x: renderer.width / 2; origin.y: renderer.height / 2; },
+ Translate { id: txOut; x: -renderer.width / 2; y: -renderer.height / 2 },
+ Scale { id: scale; },
+ Translate { id: txIn; x: renderer.width / 2; y: renderer.height / 2 }
+ ]
+ }
+
+ SequentialAnimation {
+ PauseAnimation { duration: 5000 }
+ ParallelAnimation {
+ NumberAnimation { target: scale; property: "xScale"; to: 0.6; duration: 1000; easing.type: Easing.InOutBack }
+ NumberAnimation { target: scale; property: "yScale"; to: 0.6; duration: 1000; easing.type: Easing.InOutBack }
+ }
+ NumberAnimation { target: rotation; property: "angle"; to: 80; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: rotation; property: "angle"; to: -80; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: rotation; property: "angle"; to: 0; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: renderer; property: "opacity"; to: 0.1; duration: 1000; easing.type: Easing.InOutCubic }
+ PauseAnimation { duration: 1000 }
+ NumberAnimation { target: renderer; property: "opacity"; to: 1.0; duration: 1000; easing.type: Easing.InOutCubic }
+ ParallelAnimation {
+ NumberAnimation { target: scale; property: "xScale"; to: 1; duration: 1000; easing.type: Easing.InOutBack }
+ NumberAnimation { target: scale; property: "yScale"; to: 1; duration: 1000; easing.type: Easing.InOutBack }
+ }
+ running: true
+ loops: Animation.Infinite
+ }
+
+ Rectangle {
+ id: labelFrame
+ anchors.margins: -10
+ radius: 5
+ color: "white"
+ border.color: "black"
+ opacity: 0.5
+ anchors.fill: label
+ }
+
+ Text {
+ id: label
+ anchors.bottom: renderer.bottom
+ anchors.left: renderer.left
+ anchors.right: renderer.right
+ anchors.margins: 20
+ wrapMode: Text.WordWrap
+ text: "The squircle, using rendering code borrowed from the metalunderqml example, is rendered into a texture directly with Metal. The MTLTexture is then imported and used in a custom Qt Quick item."
+ }
+}
diff --git a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.h b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.h
new file mode 100644
index 0000000000..afc5aced97
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+#ifndef METALTEXTUREIMPORT_H
+#define METALTEXTUREIMPORT_H
+
+#include <QtQuick/QQuickItem>
+
+class CustomTextureNode;
+
+//! [1]
+class CustomTextureItem : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
+
+public:
+ CustomTextureItem();
+
+ qreal t() const { return m_t; }
+ void setT(qreal t);
+
+signals:
+ void tChanged();
+
+protected:
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
+
+private slots:
+ void invalidateSceneGraph();
+
+private:
+ void releaseResources() override;
+
+ CustomTextureNode *m_node = nullptr;
+ qreal m_t = 0;
+};
+//! [1]
+
+#endif // METALTEXTUREIMPORT_H
diff --git a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.mm b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.mm
new file mode 100644
index 0000000000..66a39083f7
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.mm
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+#include "metaltextureimport.h"
+#include <QtGui/QScreen>
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/QSGTextureProvider>
+#include <QtQuick/QSGSimpleTextureNode>
+
+#include <Metal/Metal.h>
+
+//! [1]
+class CustomTextureNode : public QSGTextureProvider, public QSGSimpleTextureNode
+{
+ Q_OBJECT
+
+public:
+ CustomTextureNode(QQuickItem *item);
+ ~CustomTextureNode();
+
+ QSGTexture *texture() const override;
+
+ void sync();
+//! [1]
+private slots:
+ void render();
+
+private:
+ enum Stage {
+ VertexStage,
+ FragmentStage
+ };
+ void prepareShader(Stage stage);
+ using FuncAndLib = QPair<id<MTLFunction>, id<MTLLibrary> >;
+ FuncAndLib compileShaderFromSource(const QByteArray &src, const QByteArray &entryPoint);
+
+ QQuickItem *m_item;
+ QQuickWindow *m_window;
+ QSize m_size;
+ qreal m_dpr;
+ id<MTLDevice> m_device = nil;
+ id<MTLTexture> m_texture = nil;
+
+ bool m_initialized = false;
+ QByteArray m_vert;
+ QByteArray m_vertEntryPoint;
+ QByteArray m_frag;
+ QByteArray m_fragEntryPoint;
+ FuncAndLib m_vs;
+ FuncAndLib m_fs;
+ id<MTLBuffer> m_vbuf;
+ id<MTLBuffer> m_ubuf[3];
+ id<MTLRenderPipelineState> m_pipeline;
+
+ float m_t;
+};
+
+CustomTextureItem::CustomTextureItem()
+{
+ setFlag(ItemHasContents, true);
+}
+
+// The beauty of using a true QSGNode: no need for complicated cleanup
+// arrangements, unlike in other examples like metalunderqml, because the
+// scenegraph will handle destroying the node at the appropriate time.
+
+void CustomTextureItem::invalidateSceneGraph() // called on the render thread when the scenegraph is invalidated
+{
+ m_node = nullptr;
+}
+
+void CustomTextureItem::releaseResources() // called on the gui thread if the item is removed from scene
+{
+ m_node = nullptr;
+}
+
+//! [2]
+QSGNode *CustomTextureItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
+{
+ CustomTextureNode *n = static_cast<CustomTextureNode *>(node);
+
+ if (!n && (width() <= 0 || height() <= 0))
+ return nullptr;
+
+ if (!n) {
+ m_node = new CustomTextureNode(this);
+ n = m_node;
+ }
+
+ m_node->sync();
+
+ n->setTextureCoordinatesTransform(QSGSimpleTextureNode::NoTransform);
+ n->setFiltering(QSGTexture::Linear);
+ n->setRect(0, 0, width(), height());
+
+ window()->update(); // ensure getting to beforeRendering() at some point
+
+ return n;
+}
+//! [2]
+
+void CustomTextureItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+
+ if (newGeometry.size() != oldGeometry.size())
+ update();
+}
+
+void CustomTextureItem::setT(qreal t)
+{
+ if (t == m_t)
+ return;
+
+ m_t = t;
+ emit tChanged();
+
+ update();
+}
+
+//! [3]
+CustomTextureNode::CustomTextureNode(QQuickItem *item)
+ : m_item(item)
+{
+ m_window = m_item->window();
+ connect(m_window, &QQuickWindow::beforeRendering, this, &CustomTextureNode::render);
+ connect(m_window, &QQuickWindow::screenChanged, this, [this]() {
+ if (m_window->effectiveDevicePixelRatio() != m_dpr)
+ m_item->update();
+ });
+//! [3]
+ m_vs.first = nil;
+ m_vs.second = nil;
+
+ m_fs.first = nil;
+ m_fs.second = nil;
+
+ m_vbuf = nil;
+
+ for (int i = 0; i < 3; ++i)
+ m_ubuf[i] = nil;
+
+ m_pipeline = nil;
+
+ qDebug("renderer created");
+}
+
+CustomTextureNode::~CustomTextureNode()
+{
+ [m_pipeline release];
+
+ [m_vbuf release];
+
+ for (int i = 0; i < 3; ++i)
+ [m_ubuf[i] release];
+
+ [m_vs.first release];
+ [m_vs.second release];
+
+ [m_fs.first release];
+ [m_fs.second release];
+
+ delete texture();
+ [m_texture release];
+
+ qDebug("renderer destroyed");
+}
+
+QSGTexture *CustomTextureNode::texture() const
+{
+ return QSGSimpleTextureNode::texture();
+}
+
+static const float vertices[] = {
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ 1, 1
+};
+
+const int UBUF_SIZE = 4;
+
+//! [4]
+void CustomTextureNode::sync()
+{
+ m_dpr = m_window->effectiveDevicePixelRatio();
+ const QSize newSize = m_window->size() * m_dpr;
+ bool needsNew = false;
+
+ if (!texture())
+ needsNew = true;
+
+ if (newSize != m_size) {
+ needsNew = true;
+ m_size = newSize;
+ }
+
+ if (needsNew) {
+ delete texture();
+ [m_texture release];
+
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ m_device = (id<MTLDevice>) rif->getResource(m_window, QSGRendererInterface::DeviceResource);
+ Q_ASSERT(m_device);
+
+ MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
+ desc.textureType = MTLTextureType2D;
+ desc.pixelFormat = MTLPixelFormatRGBA8Unorm;
+ desc.width = m_size.width();
+ desc.height = m_size.height();
+ desc.mipmapLevelCount = 1;
+ desc.resourceOptions = MTLResourceStorageModePrivate;
+ desc.storageMode = MTLStorageModePrivate;
+ desc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
+ m_texture = [m_device newTextureWithDescriptor: desc];
+ [desc release];
+
+ QSGTexture *wrapper = m_window->createTextureFromNativeObject(QQuickWindow::NativeObjectTexture,
+ &m_texture,
+ 0,
+ m_size);
+
+ qDebug() << "Got QSGTexture wrapper" << wrapper << "for an MTLTexture of size" << m_size;
+
+ setTexture(wrapper);
+ }
+//! [4]
+ if (!m_initialized && texture()) {
+ m_initialized = true;
+
+ prepareShader(VertexStage);
+ prepareShader(FragmentStage);
+
+ m_vs = compileShaderFromSource(m_vert, m_vertEntryPoint);
+ m_fs = compileShaderFromSource(m_frag, m_fragEntryPoint);
+
+ const int framesInFlight = m_window->graphicsStateInfo().framesInFlight;
+
+ m_vbuf = [m_device newBufferWithLength: sizeof(vertices) options: MTLResourceStorageModeShared];
+ void *p = [m_vbuf contents];
+ memcpy(p, vertices, sizeof(vertices));
+
+ for (int i = 0; i < framesInFlight; ++i)
+ m_ubuf[i] = [m_device newBufferWithLength: UBUF_SIZE options: MTLResourceStorageModeShared];
+
+ MTLVertexDescriptor *inputLayout = [MTLVertexDescriptor vertexDescriptor];
+ inputLayout.attributes[0].format = MTLVertexFormatFloat2;
+ inputLayout.attributes[0].offset = 0;
+ inputLayout.attributes[0].bufferIndex = 1; // ubuf is 0, vbuf is 1
+ inputLayout.layouts[1].stride = 2 * sizeof(float);
+
+ MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc] init];
+ rpDesc.vertexDescriptor = inputLayout;
+
+ rpDesc.vertexFunction = m_vs.first;
+ rpDesc.fragmentFunction = m_fs.first;
+
+ rpDesc.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm;
+ rpDesc.colorAttachments[0].blendingEnabled = true;
+ rpDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
+ rpDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
+ rpDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;
+ rpDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;
+
+ NSError *err = nil;
+ m_pipeline = [m_device newRenderPipelineStateWithDescriptor: rpDesc error: &err];
+ if (!m_pipeline) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qFatal("Failed to create render pipeline state: %s", qPrintable(msg));
+ }
+ [rpDesc release];
+
+ qDebug("resources initialized");
+ }
+
+//! [5]
+ m_t = float(static_cast<CustomTextureItem *>(m_item)->t());
+//! [5]
+}
+
+// This is hooked up to beforeRendering() so we can start our own render
+// command encoder. If we instead wanted to use the scenegraph's render command
+// encoder (targeting the window), it should be connected to
+// beforeRenderPassRecording() instead.
+//! [6]
+void CustomTextureNode::render()
+{
+ if (!m_initialized)
+ return;
+
+ // Render to m_texture.
+ MTLRenderPassDescriptor *renderpassdesc = [MTLRenderPassDescriptor renderPassDescriptor];
+ MTLClearColor c = MTLClearColorMake(0, 0, 0, 1);
+ renderpassdesc.colorAttachments[0].loadAction = MTLLoadActionClear;
+ renderpassdesc.colorAttachments[0].storeAction = MTLStoreActionStore;
+ renderpassdesc.colorAttachments[0].clearColor = c;
+ renderpassdesc.colorAttachments[0].texture = m_texture;
+
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ id<MTLCommandBuffer> cb = (id<MTLCommandBuffer>) rif->getResource(m_window, QSGRendererInterface::CommandListResource);
+ Q_ASSERT(cb);
+ id<MTLRenderCommandEncoder> encoder = [cb renderCommandEncoderWithDescriptor: renderpassdesc];
+
+ const QQuickWindow::GraphicsStateInfo &stateInfo(m_window->graphicsStateInfo());
+ void *p = [m_ubuf[stateInfo.currentFrameSlot] contents];
+ memcpy(p, &m_t, 4);
+
+ MTLViewport vp;
+ vp.originX = 0;
+ vp.originY = 0;
+ vp.width = m_size.width();
+ vp.height = m_size.height();
+ vp.znear = 0;
+ vp.zfar = 1;
+ [encoder setViewport: vp];
+
+ [encoder setFragmentBuffer: m_ubuf[stateInfo.currentFrameSlot] offset: 0 atIndex: 0];
+ [encoder setVertexBuffer: m_vbuf offset: 0 atIndex: 1];
+ [encoder setRenderPipelineState: m_pipeline];
+ [encoder drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: 4 instanceCount: 1 baseInstance: 0];
+
+ [encoder endEncoding];
+}
+//! [6]
+
+void CustomTextureNode::prepareShader(Stage stage)
+{
+ QString filename;
+ if (stage == VertexStage) {
+ filename = QLatin1String(":/scenegraph/metaltextureimport/squircle.vert");
+ } else {
+ Q_ASSERT(stage == FragmentStage);
+ filename = QLatin1String(":/scenegraph/metaltextureimport/squircle.frag");
+ }
+ QFile f(filename);
+ if (!f.open(QIODevice::ReadOnly))
+ qFatal("Failed to read shader %s", qPrintable(filename));
+
+ const QByteArray contents = f.readAll();
+
+ if (stage == VertexStage) {
+ m_vert = contents;
+ Q_ASSERT(!m_vert.isEmpty());
+ m_vertEntryPoint = QByteArrayLiteral("main0");
+ } else {
+ m_frag = contents;
+ Q_ASSERT(!m_frag.isEmpty());
+ m_fragEntryPoint = QByteArrayLiteral("main0");
+ }
+}
+
+CustomTextureNode::FuncAndLib CustomTextureNode::compileShaderFromSource(const QByteArray &src, const QByteArray &entryPoint)
+{
+ FuncAndLib fl;
+
+ NSString *srcstr = [NSString stringWithUTF8String: src.constData()];
+ MTLCompileOptions *opts = [[MTLCompileOptions alloc] init];
+ opts.languageVersion = MTLLanguageVersion1_2;
+ NSError *err = nil;
+ fl.second = [m_device newLibraryWithSource: srcstr options: opts error: &err];
+ [opts release];
+ // srcstr is autoreleased
+
+ if (err) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qFatal("%s", qPrintable(msg));
+ return fl;
+ }
+
+ NSString *name = [NSString stringWithUTF8String: entryPoint.constData()];
+ fl.first = [fl.second newFunctionWithName: name];
+ [name release];
+
+ return fl;
+}
+
+#include "metaltextureimport.moc"
diff --git a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro
new file mode 100644
index 0000000000..5b11606946
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro
@@ -0,0 +1,12 @@
+!macos: error("This example requires macOS")
+
+QT += qml quick
+
+HEADERS += metaltextureimport.h
+SOURCES += metaltextureimport.mm main.cpp
+RESOURCES += metaltextureimport.qrc
+
+LIBS += -framework Metal -framework AppKit
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/metaltextureimport
+INSTALLS += target
diff --git a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.qrc b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.qrc
new file mode 100644
index 0000000000..7a8dd7a860
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/scenegraph/metaltextureimport">
+ <file>main.qml</file>
+ <file>squircle.vert</file>
+ <file>squircle.frag</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/scenegraph/metaltextureimport/squircle.frag b/examples/quick/scenegraph/metaltextureimport/squircle.frag
new file mode 100644
index 0000000000..15f34624fe
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/squircle.frag
@@ -0,0 +1,29 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct buf
+{
+ float t;
+};
+
+struct main0_out
+{
+ float4 fragColor [[color(0)]];
+};
+
+struct main0_in
+{
+ float2 coords [[user(locn0)]];
+};
+
+fragment main0_out main0(main0_in in [[stage_in]], constant buf& ubuf [[buffer(0)]])
+{
+ main0_out out = {};
+ float i = 1.0 - (pow(abs(in.coords.x), 4.0) + pow(abs(in.coords.y), 4.0));
+ i = smoothstep(ubuf.t - 0.800000011920928955078125, ubuf.t + 0.800000011920928955078125, i);
+ i = floor(i * 20.0) / 20.0;
+ out.fragColor = float4((in.coords * 0.5) + float2(0.5), i, i);
+ return out;
+}
diff --git a/examples/quick/scenegraph/metaltextureimport/squircle.vert b/examples/quick/scenegraph/metaltextureimport/squircle.vert
new file mode 100644
index 0000000000..a88c59f541
--- /dev/null
+++ b/examples/quick/scenegraph/metaltextureimport/squircle.vert
@@ -0,0 +1,23 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+ float2 coords [[user(locn0)]];
+ float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+ float4 vertices [[attribute(0)]];
+};
+
+vertex main0_out main0(main0_in in [[stage_in]])
+{
+ main0_out out = {};
+ out.gl_Position = in.vertices;
+ out.coords = in.vertices.xy;
+ return out;
+}
diff --git a/examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc b/examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc
index d499f47de3..fb28270315 100644
--- a/examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc
+++ b/examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc
@@ -61,8 +61,9 @@
program that draws the squircles.
The example is equivalent in most ways to the \l{Scene Graph - OpenGL Under
- QML}{OpenGL Under QML} and \l{Scene Graph - Direct3D 11 Under QML}{Direct3D
- 11 Under QML} examples, they all render the same custom content, just via
- different native APIs.
+ QML}{OpenGL Under QML}, \l{Scene Graph - Direct3D 11 Under QML}{Direct3D 11
+ Under QML}, and \l{Scene Graph - Vulkan Under QML}{Vulkan Under QML}
+ examples, they all render the same custom content, just via different
+ native APIs.
*/
diff --git a/examples/quick/scenegraph/metalunderqml/main.cpp b/examples/quick/scenegraph/metalunderqml/main.cpp
index 5ad337abb1..3e620137cd 100644
--- a/examples/quick/scenegraph/metalunderqml/main.cpp
+++ b/examples/quick/scenegraph/metalunderqml/main.cpp
@@ -56,7 +56,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<MetalSquircle>("MetalUnderQML", 1, 0, "MetalSquircle");
+ qmlRegisterTypesAndRevisions<MetalSquircle>("MetalUnderQML", 1);
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::MetalRhi);
diff --git a/examples/quick/scenegraph/metalunderqml/metalsquircle.h b/examples/quick/scenegraph/metalunderqml/metalsquircle.h
index 43c4afad21..18db7d45f3 100644
--- a/examples/quick/scenegraph/metalunderqml/metalsquircle.h
+++ b/examples/quick/scenegraph/metalunderqml/metalsquircle.h
@@ -59,6 +59,7 @@ class MetalSquircle : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
+ QML_ELEMENT
public:
MetalSquircle();
diff --git a/examples/quick/scenegraph/metalunderqml/metalsquircle.mm b/examples/quick/scenegraph/metalunderqml/metalsquircle.mm
index 92aceeb433..5ca6daa01a 100644
--- a/examples/quick/scenegraph/metalunderqml/metalsquircle.mm
+++ b/examples/quick/scenegraph/metalunderqml/metalsquircle.mm
@@ -186,7 +186,12 @@ void MetalSquircle::sync()
{
if (!m_renderer) {
m_renderer = new SquircleRenderer;
+ // Initializing resources is done before starting to encode render
+ // commands, regardless of wanting an underlay or overlay.
connect(window(), &QQuickWindow::beforeRendering, m_renderer, &SquircleRenderer::frameStart, Qt::DirectConnection);
+ // Here we want an underlay and therefore connect to
+ // beforeRenderPassRecording. Changing to afterRenderPassRecording
+ // would render the squircle on top (overlay).
connect(window(), &QQuickWindow::beforeRenderPassRecording, m_renderer, &SquircleRenderer::mainPassRecordingStart, Qt::DirectConnection);
}
m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
@@ -210,7 +215,7 @@ void SquircleRenderer::frameStart()
prepareShader(FragmentStage);
if (!m_initialized)
- init(m_window->graphicsStateInfo()->framesInFlight);
+ init(m_window->graphicsStateInfo().framesInFlight);
}
static const float vertices[] = {
@@ -228,7 +233,7 @@ void SquircleRenderer::mainPassRecordingStart()
// the scenegraph's main renderpass. It does not create its own passes,
// rendertargets, etc. so no synchronization is needed.
- const QQuickWindow::GraphicsStateInfo *stateInfo = m_window->graphicsStateInfo();
+ const QQuickWindow::GraphicsStateInfo &stateInfo(m_window->graphicsStateInfo());
QSGRendererInterface *rif = m_window->rendererInterface();
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>) rif->getResource(
@@ -237,7 +242,7 @@ void SquircleRenderer::mainPassRecordingStart()
m_window->beginExternalCommands();
- void *p = [m_ubuf[stateInfo->currentFrameSlot] contents];
+ void *p = [m_ubuf[stateInfo.currentFrameSlot] contents];
float t = m_t;
memcpy(p, &t, 4);
@@ -250,7 +255,7 @@ void SquircleRenderer::mainPassRecordingStart()
vp.zfar = 1;
[encoder setViewport: vp];
- [encoder setFragmentBuffer: m_ubuf[stateInfo->currentFrameSlot] offset: 0 atIndex: 0];
+ [encoder setFragmentBuffer: m_ubuf[stateInfo.currentFrameSlot] offset: 0 atIndex: 0];
[encoder setVertexBuffer: m_vbuf offset: 0 atIndex: 1];
[encoder setRenderPipelineState: m_pipeline];
[encoder drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: 4 instanceCount: 1 baseInstance: 0];
diff --git a/examples/quick/scenegraph/metalunderqml/metalunderqml.pro b/examples/quick/scenegraph/metalunderqml/metalunderqml.pro
index 9b27638a6d..9fd131fe1b 100644
--- a/examples/quick/scenegraph/metalunderqml/metalunderqml.pro
+++ b/examples/quick/scenegraph/metalunderqml/metalunderqml.pro
@@ -1,3 +1,5 @@
+!macos: error("This example requires macOS")
+
QT += qml quick
HEADERS += metalsquircle.h
diff --git a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
index ed46b40420..9676815c44 100644
--- a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
+++ b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
@@ -50,9 +50,10 @@
in the QML file and this value is used by the OpenGL shader
program that draws the squircles.
- The example is equivalent in most ways to the \l{Scene Graph - Direct3D 11 Under
- QML}{Direct3D 11 Under QML} and \l{Scene Graph - Metal Under QML}{Metal Under
- QML} examples, they all render the same custom content, just via different
+ The example is equivalent in most ways to the \l{Scene Graph - Direct3D 11
+ Under QML}{Direct3D 11 Under QML}, \l{Scene Graph - Metal Under QML}{Metal
+ Under QML}, and \l{Scene Graph - Vulkan Under QML}{Vulkan Under QML}
+ examples, they all render the same custom content, just via different
native APIs.
\snippet scenegraph/openglunderqml/squircle.h 2
diff --git a/examples/quick/scenegraph/openglunderqml/main.cpp b/examples/quick/scenegraph/openglunderqml/main.cpp
index 022d6a75bb..c04d0da68f 100644
--- a/examples/quick/scenegraph/openglunderqml/main.cpp
+++ b/examples/quick/scenegraph/openglunderqml/main.cpp
@@ -59,7 +59,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<Squircle>("OpenGLUnderQML", 1, 0, "Squircle");
+ qmlRegisterTypesAndRevisions<Squircle>("OpenGLUnderQML", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.h b/examples/quick/scenegraph/openglunderqml/squircle.h
index 1b9995bc1e..c24fdd50c2 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.h
+++ b/examples/quick/scenegraph/openglunderqml/squircle.h
@@ -86,6 +86,7 @@ class Squircle : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
+ QML_ELEMENT
public:
Squircle();
diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.cpp b/examples/quick/scenegraph/rendernode/customrenderitem.cpp
index 67a9cccfc6..e55cf0a2f4 100644
--- a/examples/quick/scenegraph/rendernode/customrenderitem.cpp
+++ b/examples/quick/scenegraph/rendernode/customrenderitem.cpp
@@ -70,48 +70,58 @@ CustomRenderItem::CustomRenderItem(QQuickItem *parent)
QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
QSGRenderNode *n = static_cast<QSGRenderNode *>(node);
- if (!n) {
- QSGRendererInterface *ri = window()->rendererInterface();
- if (!ri)
- return nullptr;
- switch (ri->graphicsApi()) {
- case QSGRendererInterface::OpenGL:
- Q_FALLTHROUGH();
- case QSGRendererInterface::OpenGLRhi:
+
+ QSGRendererInterface *ri = window()->rendererInterface();
+ if (!ri)
+ return nullptr;
+
+ switch (ri->graphicsApi()) {
+ case QSGRendererInterface::OpenGL:
+ Q_FALLTHROUGH();
+ case QSGRendererInterface::OpenGLRhi:
#if QT_CONFIG(opengl)
- n = new OpenGLRenderNode(this);
+ if (!n)
+ n = new OpenGLRenderNode;
+ static_cast<OpenGLRenderNode *>(n)->sync(this);
#endif
- break;
+ break;
- case QSGRendererInterface::MetalRhi:
-#ifdef Q_OS_DARWIN
- {
- MetalRenderNode *metalNode = new MetalRenderNode(this);
+ case QSGRendererInterface::MetalRhi:
+// Restore when QTBUG-78580 is done and the .pro is updated accordingly
+//#ifdef Q_OS_DARWIN
+#ifdef Q_OS_MACOS
+ if (!n) {
+ MetalRenderNode *metalNode = new MetalRenderNode;
n = metalNode;
metalNode->resourceBuilder()->setWindow(window());
QObject::connect(window(), &QQuickWindow::beforeRendering,
metalNode->resourceBuilder(), &MetalRenderNodeResourceBuilder::build);
}
+ static_cast<MetalRenderNode *>(n)->sync(this);
#endif
- break;
+ break;
- case QSGRendererInterface::Direct3D12: // ### Qt 6: remove
+ case QSGRendererInterface::Direct3D12: // ### Qt 6: remove
#if QT_CONFIG(d3d12)
- n = new D3D12RenderNode(this);
+ if (!n)
+ n = new D3D12RenderNode;
+ static_cast<D3D12RenderNode *>(n)->sync(this);
#endif
- break;
+ break;
- case QSGRendererInterface::Software:
- n = new SoftwareRenderNode(this);
- break;
-
- default:
- break;
- }
+ case QSGRendererInterface::Software:
if (!n)
- qWarning("QSGRendererInterface reports unknown graphics API %d", ri->graphicsApi());
+ n = new SoftwareRenderNode;
+ static_cast<SoftwareRenderNode *>(n)->sync(this);
+ break;
+
+ default:
+ break;
}
+ if (!n)
+ qWarning("QSGRendererInterface reports unknown graphics API %d", ri->graphicsApi());
+
return n;
}
//! [2]
diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.h b/examples/quick/scenegraph/rendernode/customrenderitem.h
index a0ac3468e4..74115b2505 100644
--- a/examples/quick/scenegraph/rendernode/customrenderitem.h
+++ b/examples/quick/scenegraph/rendernode/customrenderitem.h
@@ -56,6 +56,7 @@
class CustomRenderItem : public QQuickItem
{
Q_OBJECT
+ QML_ELEMENT
public:
CustomRenderItem(QQuickItem *parent = nullptr);
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
index 878b022950..e85811c089 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
@@ -58,11 +58,6 @@
#if QT_CONFIG(d3d12)
-D3D12RenderNode::D3D12RenderNode(QQuickItem *item)
- : m_item(item)
-{
-}
-
D3D12RenderNode::~D3D12RenderNode()
{
releaseResources();
@@ -87,8 +82,8 @@ void D3D12RenderNode::releaseResources()
void D3D12RenderNode::init()
{
- QSGRendererInterface *rif = m_item->window()->rendererInterface();
- m_device = static_cast<ID3D12Device *>(rif->getResource(m_item->window(), QSGRendererInterface::DeviceResource));
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ m_device = static_cast<ID3D12Device *>(rif->getResource(m_window, QSGRendererInterface::DeviceResource));
Q_ASSERT(m_device);
D3D12_ROOT_PARAMETER rootParameter;
@@ -178,7 +173,7 @@ void D3D12RenderNode::init()
psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; // not in use due to !DepthEnable, but this would be the correct format otherwise
// We are rendering on the default render target so if the QuickWindow/View
// has requested samples > 0 then we have to follow suit.
- const uint samples = qMax(1, m_item->window()->format().samples());
+ const uint samples = qMax(1, m_window->format().samples());
psoDesc.SampleDesc.Count = samples;
if (samples > 1) {
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msaaInfo = {};
@@ -257,9 +252,9 @@ void D3D12RenderNode::render(const RenderState *state)
if (!m_device)
init();
- QSGRendererInterface *rif = m_item->window()->rendererInterface();
+ QSGRendererInterface *rif = m_window->rendererInterface();
ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>(
- rif->getResource(m_item->window(), QSGRendererInterface::CommandListResource));
+ rif->getResource(m_window, QSGRendererInterface::CommandListResource));
Q_ASSERT(commandList);
const int msize = 16 * sizeof(float);
@@ -268,9 +263,9 @@ void D3D12RenderNode::render(const RenderState *state)
const float opacity = inheritedOpacity();
memcpy(cbPtr + 2 * msize, &opacity, sizeof(float));
- const QPointF p0(m_item->width() - 1, m_item->height() - 1);
+ const QPointF p0(m_width - 1, m_height - 1);
const QPointF p1(0, 0);
- const QPointF p2(0, m_item->height() - 1);
+ const QPointF p2(0, m_height - 1);
float *vp = reinterpret_cast<float *>(vbPtr);
*vp++ = p0.x();
@@ -301,7 +296,14 @@ QSGRenderNode::RenderingFlags D3D12RenderNode::flags() const
QRectF D3D12RenderNode::rect() const
{
- return QRect(0, 0, m_item->width(), m_item->height());
+ return QRect(0, 0, m_width, m_height);
+}
+
+void D3D12RenderNode::sync(QQuickItem *item)
+{
+ m_window = item->window();
+ m_width = item->width();
+ m_height = item->height();
}
#endif // d3d12
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.h b/examples/quick/scenegraph/rendernode/d3d12renderer.h
index ec4b5f85e8..7186b72c04 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.h
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.h
@@ -52,11 +52,10 @@
#define D3D12RENDERER_H
#include <qsgrendernode.h>
+#include <QQuickItem>
#if QT_CONFIG(d3d12)
-QT_FORWARD_DECLARE_CLASS(QQuickItem)
-
#include <d3d12.h>
#include <wrl/client.h>
@@ -65,7 +64,6 @@ using namespace Microsoft::WRL;
class D3D12RenderNode : public QSGRenderNode
{
public:
- D3D12RenderNode(QQuickItem *item);
~D3D12RenderNode();
void render(const RenderState *state) override;
@@ -73,10 +71,15 @@ public:
RenderingFlags flags() const override;
QRectF rect() const override;
+ void sync(QQuickItem *item);
+
private:
void init();
- QQuickItem *m_item;
+ QQuickWindow *m_window = nullptr;
+ int m_width = 0;
+ int m_height = 0;
+
ID3D12Device *m_device = nullptr;
ComPtr<ID3D12PipelineState> pipelineState;
ComPtr<ID3D12RootSignature> rootSignature;
diff --git a/examples/quick/scenegraph/rendernode/main.cpp b/examples/quick/scenegraph/rendernode/main.cpp
index 146d787e50..b1dfe47829 100644
--- a/examples/quick/scenegraph/rendernode/main.cpp
+++ b/examples/quick/scenegraph/rendernode/main.cpp
@@ -59,7 +59,7 @@ int main(int argc, char **argv)
QGuiApplication app(argc, argv);
//! [1]
- qmlRegisterType<CustomRenderItem>("SceneGraphRendering", 2, 0, "CustomRenderItem");
+ qmlRegisterTypesAndRevisions<CustomRenderItem>("SceneGraphRendering", 2);
//! [1]
QQuickView view;
diff --git a/examples/quick/scenegraph/rendernode/metalrenderer.h b/examples/quick/scenegraph/rendernode/metalrenderer.h
index 77c9892313..cf7fccb930 100644
--- a/examples/quick/scenegraph/rendernode/metalrenderer.h
+++ b/examples/quick/scenegraph/rendernode/metalrenderer.h
@@ -52,14 +52,13 @@
#define METALRENDERER_H
#include <qsgrendernode.h>
+#include <QQuickItem>
-#ifdef Q_OS_DARWIN
+//#ifdef Q_OS_DARWIN
+#ifdef Q_OS_MACOS
QT_BEGIN_NAMESPACE
-class QQuickItem;
-class QQuickWindow;
-
QT_END_NAMESPACE
class MetalRenderNodeResourceBuilder : public QObject
@@ -79,7 +78,7 @@ private:
class MetalRenderNode : public QSGRenderNode
{
public:
- MetalRenderNode(QQuickItem *item);
+ MetalRenderNode();
~MetalRenderNode();
void render(const RenderState *state) override;
@@ -90,9 +89,14 @@ public:
MetalRenderNodeResourceBuilder *resourceBuilder() { return &m_resourceBuilder; }
+ void sync(QQuickItem *item);
+
private:
- QQuickItem *m_item;
MetalRenderNodeResourceBuilder m_resourceBuilder;
+ QQuickWindow *m_window = nullptr;
+ int m_width = 0;
+ int m_height = 0;
+ int m_outputHeight = 0;
};
#endif // Q_OS_DARWIN
diff --git a/examples/quick/scenegraph/rendernode/metalrenderer.mm b/examples/quick/scenegraph/rendernode/metalrenderer.mm
index 4cb973abee..b83dc62c48 100644
--- a/examples/quick/scenegraph/rendernode/metalrenderer.mm
+++ b/examples/quick/scenegraph/rendernode/metalrenderer.mm
@@ -131,7 +131,7 @@ void MetalRenderNodeResourceBuilder::build()
g.fs = compileShaderFromSource(g.fsSource, QByteArrayLiteral("main0"));
}
- const int framesInFlight = m_window->graphicsStateInfo()->framesInFlight;
+ const int framesInFlight = m_window->graphicsStateInfo().framesInFlight;
// For simplicity's sake we use shared mode (something like host visible +
// host coherent) for everything.
@@ -214,8 +214,7 @@ void MetalRenderNodeResourceBuilder::build()
}
}
-MetalRenderNode::MetalRenderNode(QQuickItem *item)
- : m_item(item)
+MetalRenderNode::MetalRenderNode()
{
g.vs.first = g.fs.first = nil;
g.vs.second = g.fs.second = nil;
@@ -258,14 +257,14 @@ void MetalRenderNode::releaseResources()
void MetalRenderNode::render(const RenderState *state)
{
- QQuickWindow *window = m_item->window();
- const QQuickWindow::GraphicsStateInfo *stateInfo = window->graphicsStateInfo();
- id<MTLBuffer> vbuf = g.vbuf[stateInfo->currentFrameSlot];
- id<MTLBuffer> ubuf = g.ubuf[stateInfo->currentFrameSlot];
+ Q_ASSERT(m_window);
+ const QQuickWindow::GraphicsStateInfo &stateInfo(m_window->graphicsStateInfo());
+ id<MTLBuffer> vbuf = g.vbuf[stateInfo.currentFrameSlot];
+ id<MTLBuffer> ubuf = g.ubuf[stateInfo.currentFrameSlot];
- QPointF p0(m_item->width() - 1, m_item->height() - 1);
+ QPointF p0(m_width - 1, m_height - 1);
QPointF p1(0, 0);
- QPointF p2(0, m_item->height() - 1);
+ QPointF p2(0, m_height - 1);
float vertices[6] = { float(p0.x()), float(p0.y()),
float(p1.x()), float(p1.y()),
@@ -280,9 +279,9 @@ void MetalRenderNode::render(const RenderState *state)
memcpy(p, mvp.constData(), 64);
memcpy(p + 64, &opacity, 4);
- QSGRendererInterface *rif = window->rendererInterface();
+ QSGRendererInterface *rif = m_window->rendererInterface();
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>) rif->getResource(
- window, QSGRendererInterface::CommandEncoderResource);
+ m_window, QSGRendererInterface::CommandEncoderResource);
Q_ASSERT(encoder);
[encoder setVertexBuffer: vbuf offset: 0 atIndex: 1];
@@ -296,7 +295,7 @@ void MetalRenderNode::render(const RenderState *state)
const QRect r = state->scissorRect(); // bottom-up
MTLScissorRect s;
s.x = r.x();
- s.y = (window->height() * window->effectiveDevicePixelRatio()) - (r.y() + r.height());
+ s.y = m_outputHeight - (r.y() + r.height());
s.width = r.width();
s.height = r.height();
[encoder setScissorRect: s];
@@ -322,5 +321,13 @@ QSGRenderNode::RenderingFlags MetalRenderNode::flags() const
QRectF MetalRenderNode::rect() const
{
- return QRect(0, 0, m_item->width(), m_item->height());
+ return QRect(0, 0, m_width, m_height);
+}
+
+void MetalRenderNode::sync(QQuickItem *item)
+{
+ m_window = item->window();
+ m_width = item->width();
+ m_height = item->height();
+ m_outputHeight = m_window->height() * m_window->effectiveDevicePixelRatio();
}
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.cpp b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
index 0633731617..a4e619bea9 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
@@ -58,11 +58,6 @@
#include <QOpenGLFunctions>
//! [1]
-OpenGLRenderNode::OpenGLRenderNode(QQuickItem *item)
- : m_item(item)
-{
-}
-
OpenGLRenderNode::~OpenGLRenderNode()
{
releaseResources();
@@ -138,9 +133,9 @@ void OpenGLRenderNode::render(const RenderState *state)
m_vbo->bind();
//! [5]
- QPointF p0(m_item->width() - 1, m_item->height() - 1);
+ QPointF p0(m_width - 1, m_height - 1);
QPointF p1(0, 0);
- QPointF p2(0, m_item->height() - 1);
+ QPointF p2(0, m_height - 1);
GLfloat vertices[6] = { GLfloat(p0.x()), GLfloat(p0.y()),
GLfloat(p1.x()), GLfloat(p1.y()),
@@ -192,8 +187,14 @@ QSGRenderNode::RenderingFlags OpenGLRenderNode::flags() const
QRectF OpenGLRenderNode::rect() const
{
- return QRect(0, 0, m_item->width(), m_item->height());
+ return QRect(0, 0, m_width, m_height);
}
//! [4]
+void OpenGLRenderNode::sync(QQuickItem *item)
+{
+ m_width = item->width();
+ m_height = item->height();
+}
+
#endif // opengl
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.h b/examples/quick/scenegraph/rendernode/openglrenderer.h
index 8d2d3caad1..1e7977481a 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.h
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.h
@@ -52,12 +52,12 @@
#define OPENGLRENDERER_H
#include <qsgrendernode.h>
+#include <QQuickItem>
#if QT_CONFIG(opengl)
QT_BEGIN_NAMESPACE
-class QQuickItem;
class QOpenGLShaderProgram;
class QOpenGLBuffer;
@@ -67,7 +67,6 @@ QT_END_NAMESPACE
class OpenGLRenderNode : public QSGRenderNode
{
public:
- OpenGLRenderNode(QQuickItem *item);
~OpenGLRenderNode();
void render(const RenderState *state) override;
@@ -77,10 +76,13 @@ public:
QRectF rect() const override;
//! [1]
+ void sync(QQuickItem *item);
+
private:
void init();
- QQuickItem *m_item;
+ int m_width = 0;
+ int m_height = 0;
QOpenGLShaderProgram *m_program = nullptr;
int m_matrixUniform;
int m_opacityUniform;
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
index 0a0ec4b485..bba364ac97 100644
--- a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
@@ -54,11 +54,6 @@
#include <QSGRendererInterface>
#include <QPainter>
-SoftwareRenderNode::SoftwareRenderNode(QQuickItem *item)
- : m_item(item)
-{
-}
-
SoftwareRenderNode::~SoftwareRenderNode()
{
releaseResources();
@@ -70,8 +65,10 @@ void SoftwareRenderNode::releaseResources()
void SoftwareRenderNode::render(const RenderState *renderState)
{
- QSGRendererInterface *rif = m_item->window()->rendererInterface();
- QPainter *p = static_cast<QPainter *>(rif->getResource(m_item->window(), QSGRendererInterface::PainterResource));
+ Q_ASSERT(m_window);
+
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ QPainter *p = static_cast<QPainter *>(rif->getResource(m_window, QSGRendererInterface::PainterResource));
Q_ASSERT(p);
const QRegion *clipRegion = renderState->clipRegion();
@@ -81,15 +78,15 @@ void SoftwareRenderNode::render(const RenderState *renderState)
p->setTransform(matrix()->toTransform());
p->setOpacity(inheritedOpacity());
- const QPointF p0(m_item->width() - 1, m_item->height() - 1);
+ const QPointF p0(m_width - 1, m_height - 1);
const QPointF p1(0, 0);
- const QPointF p2(0, m_item->height() - 1);
+ const QPointF p2(0, m_height - 1);
QPainterPath path(p0);
path.lineTo(p1);
path.lineTo(p2);
path.closeSubpath();
- QLinearGradient gradient(QPointF(0, 0), QPointF(m_item->width(), m_item->height()));
+ QLinearGradient gradient(QPointF(0, 0), QPointF(m_width, m_height));
gradient.setColorAt(0, Qt::green);
gradient.setColorAt(1, Qt::red);
@@ -108,5 +105,12 @@ QSGRenderNode::RenderingFlags SoftwareRenderNode::flags() const
QRectF SoftwareRenderNode::rect() const
{
- return QRect(0, 0, m_item->width(), m_item->height());
+ return QRect(0, 0, m_width, m_height);
+}
+
+void SoftwareRenderNode::sync(QQuickItem *item)
+{
+ m_window = item->window();
+ m_width = item->width();
+ m_height = item->height();
}
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.h b/examples/quick/scenegraph/rendernode/softwarerenderer.h
index cc2aaf7ed3..6091a13ca3 100644
--- a/examples/quick/scenegraph/rendernode/softwarerenderer.h
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.h
@@ -57,7 +57,6 @@
class SoftwareRenderNode : public QSGRenderNode
{
public:
- SoftwareRenderNode(QQuickItem *item);
~SoftwareRenderNode();
void render(const RenderState *state) override;
@@ -66,8 +65,12 @@ public:
RenderingFlags flags() const override;
QRectF rect() const override;
+ void sync(QQuickItem *item);
+
private:
- QQuickItem *m_item;
+ QQuickWindow *m_window = nullptr;
+ int m_width = 0;
+ int m_height = 0;
};
#endif
diff --git a/examples/quick/scenegraph/scenegraph.pro b/examples/quick/scenegraph/scenegraph.pro
index ac368c79a5..5fea3b974a 100644
--- a/examples/quick/scenegraph/scenegraph.pro
+++ b/examples/quick/scenegraph/scenegraph.pro
@@ -5,7 +5,7 @@ qtConfig(opengl(es1|es2)?) {
graph \
simplematerial \
sgengine \
- textureinsgnode \
+ fboitem \
openglunderqml \
textureinthread \
twotextureproviders
@@ -17,12 +17,18 @@ SUBDIRS += \
threadedanimation
macos {
- SUBDIRS += metalunderqml
+ SUBDIRS += \
+ metalunderqml \
+ metaltextureimport
}
win32 {
SUBDIRS += d3d11underqml
}
+qtConfig(vulkan) {
+ SUBDIRS += vulkanunderqml
+}
+
EXAMPLE_FILES += \
shared
diff --git a/examples/quick/scenegraph/simplematerial/simplematerial.cpp b/examples/quick/scenegraph/simplematerial/simplematerial.cpp
index 6773b6fb5a..55e1d879ca 100644
--- a/examples/quick/scenegraph/simplematerial/simplematerial.cpp
+++ b/examples/quick/scenegraph/simplematerial/simplematerial.cpp
@@ -157,6 +157,7 @@ class Item : public QQuickItem
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ QML_NAMED_ELEMENT(SimpleMaterialItem)
public:
@@ -203,7 +204,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<Item>("SimpleMaterial", 1, 0, "SimpleMaterialItem");
+ qmlRegisterTypesAndRevisions<Item>("SimpleMaterial", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
diff --git a/examples/quick/scenegraph/textureinthread/main.cpp b/examples/quick/scenegraph/textureinthread/main.cpp
index 7a46f25390..7c22fa7fdf 100644
--- a/examples/quick/scenegraph/textureinthread/main.cpp
+++ b/examples/quick/scenegraph/textureinthread/main.cpp
@@ -70,7 +70,7 @@ int main(int argc, char **argv)
return app.exec();
}
- qmlRegisterType<ThreadRenderer>("SceneGraphRendering", 1, 0, "Renderer");
+ qmlRegisterTypesAndRevisions<ThreadRenderer>("SceneGraphRendering", 1);
int execReturn = 0;
{
diff --git a/examples/quick/scenegraph/textureinthread/threadrenderer.h b/examples/quick/scenegraph/textureinthread/threadrenderer.h
index 8442041bf8..96c00e7b2e 100644
--- a/examples/quick/scenegraph/textureinthread/threadrenderer.h
+++ b/examples/quick/scenegraph/textureinthread/threadrenderer.h
@@ -58,6 +58,7 @@ class RenderThread;
class ThreadRenderer : public QQuickItem
{
Q_OBJECT
+ QML_NAMED_ELEMENT(Renderer)
public:
ThreadRenderer();
diff --git a/examples/quick/scenegraph/threadedanimation/main.cpp b/examples/quick/scenegraph/threadedanimation/main.cpp
index b1b0c05085..c77a291f5d 100644
--- a/examples/quick/scenegraph/threadedanimation/main.cpp
+++ b/examples/quick/scenegraph/threadedanimation/main.cpp
@@ -57,7 +57,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<Spinner>("Spinner", 1, 0, "Spinner");
+ qmlRegisterTypesAndRevisions<Spinner>("Spinner", 1);
QQuickView view;
view.setSource(QUrl("qrc:///scenegraph/threadedanimation/main.qml"));
diff --git a/examples/quick/scenegraph/threadedanimation/spinner.h b/examples/quick/scenegraph/threadedanimation/spinner.h
index c3f3394c93..fd3eaa7751 100644
--- a/examples/quick/scenegraph/threadedanimation/spinner.h
+++ b/examples/quick/scenegraph/threadedanimation/spinner.h
@@ -58,6 +58,7 @@ class Spinner : public QQuickItem
Q_OBJECT
Q_PROPERTY(bool spinning READ spinning WRITE setSpinning NOTIFY spinningChanged)
+ QML_ELEMENT
public:
Spinner();
diff --git a/examples/quick/scenegraph/twotextureproviders/main.cpp b/examples/quick/scenegraph/twotextureproviders/main.cpp
index a5d23b6adc..3f53bb6e32 100644
--- a/examples/quick/scenegraph/twotextureproviders/main.cpp
+++ b/examples/quick/scenegraph/twotextureproviders/main.cpp
@@ -58,7 +58,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<XorBlender>("SceneGraphRendering", 1, 0, "XorBlender");
+ qmlRegisterTypesAndRevisions<XorBlender>("SceneGraphRendering", 1);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
diff --git a/examples/quick/scenegraph/twotextureproviders/xorblender.h b/examples/quick/scenegraph/twotextureproviders/xorblender.h
index 94132f09fb..17557b8efd 100644
--- a/examples/quick/scenegraph/twotextureproviders/xorblender.h
+++ b/examples/quick/scenegraph/twotextureproviders/xorblender.h
@@ -58,6 +58,7 @@ class XorBlender : public QQuickItem
Q_OBJECT
Q_PROPERTY(QQuickItem *source1 READ source1 WRITE setSource1 NOTIFY source1Changed)
Q_PROPERTY(QQuickItem *source2 READ source2 WRITE setSource2 NOTIFY source2Changed)
+ QML_ELEMENT
public:
explicit XorBlender(QQuickItem *parent = 0);
diff --git a/examples/quick/scenegraph/vulkanunderqml/doc/images/vulkanunderqml-example.jpg b/examples/quick/scenegraph/vulkanunderqml/doc/images/vulkanunderqml-example.jpg
new file mode 100644
index 0000000000..c3f51b6194
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/doc/images/vulkanunderqml-example.jpg
Binary files differ
diff --git a/examples/quick/scenegraph/vulkanunderqml/doc/src/vulkanunderqml.qdoc b/examples/quick/scenegraph/vulkanunderqml/doc/src/vulkanunderqml.qdoc
new file mode 100644
index 0000000000..d11982c074
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/doc/src/vulkanunderqml.qdoc
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example scenegraph/vulkanunderqml
+ \title Scene Graph - Vulkan Under QML
+ \ingroup qtquickexamples
+ \brief Shows how to render directly with vulkan under a Qt Quick scene.
+
+ \image vulkanunderqml-example.jpg
+
+ The Vulkan Under QML example shows how an application can make use of the
+ \l QQuickWindow::beforeRendering() and \l
+ QQuickWindow::beforeRenderPassRecording() signals to draw custom Vulkan
+ content under a Qt Quick scene. This signal is emitted at the start of
+ every frame, before the scene graph starts its rendering, thus any Vulkan
+ draw calls that are made as a response to this signal, will stack under the
+ Qt Quick items. There are two signals, because the custom Vulkan commands
+ are recorded onto the same command buffer that is used by the scene graph.
+ beforeRendering() on its own is not sufficient for this because it gets
+ emitted at the start of the frame, before recording the start of a
+ renderpass instance via
+ \l{https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCmdBeginRenderPass.html}{vkCmdBeginRenderPass}.
+ By also connecting to beforeRenderPassRecording(), the application's own
+ commands and the scene graph's scaffolding will end up in the right order.
+
+ As an alternative, applications that wish to render Vulkan content
+ on top of the Qt Quick scene, can do so by connecting to the \l
+ QQuickWindow::afterRendering() and \l
+ QQuickWindow::afterRenderPassRecording() signals.
+
+ In this example, we will also see how it is possible to have
+ values that are exposed to QML which affect the Vulkan
+ rendering. We animate the threshold value using a NumberAnimation
+ in the QML file and this value is used by the SPIR-V shader
+ program that draws the squircles.
+
+ The example is equivalent in most ways to the \l{Scene Graph - OpenGL Under
+ QML}{OpenGL Under QML}, \l{Scene Graph - Direct3D 11 Under QML}{Direct3D 11
+ Under QML}, and \l{Scene Graph - Metal Under QML}{Metal Under QML}
+ examples, they all render the same custom content, just via different
+ native APIs.
+
+ */
diff --git a/examples/quick/scenegraph/vulkanunderqml/main.cpp b/examples/quick/scenegraph/vulkanunderqml/main.cpp
new file mode 100644
index 0000000000..a04497b1d6
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QtQuick/QQuickView>
+#include "vulkansquircle.h"
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<VulkanSquircle>("VulkanUnderQML", 1, 0, "VulkanSquircle");
+
+ // This example needs Vulkan. It will not run otherwise.
+ QQuickWindow::setSceneGraphBackend(QSGRendererInterface::VulkanRhi);
+
+ QQuickView view;
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:///scenegraph/vulkanunderqml/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/quick/scenegraph/vulkanunderqml/main.qml b/examples/quick/scenegraph/vulkanunderqml/main.qml
new file mode 100644
index 0000000000..c364ca7636
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/main.qml
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+//! [1]
+import QtQuick 2.0
+import VulkanUnderQML 1.0
+
+Item {
+
+ width: 320
+ height: 480
+
+ VulkanSquircle {
+ SequentialAnimation on t {
+ NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
+ NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
+ loops: Animation.Infinite
+ running: true
+ }
+ }
+//! [1] //! [2]
+ Rectangle {
+ color: Qt.rgba(1, 1, 1, 0.7)
+ radius: 10
+ border.width: 1
+ border.color: "white"
+ anchors.fill: label
+ anchors.margins: -10
+ }
+
+ Text {
+ id: label
+ color: "black"
+ wrapMode: Text.WordWrap
+ text: "The background here is a squircle rendered with raw Vulkan using the beforeRendering() and beforeRenderPassRecording() signals in QQuickWindow. This text label and its border is rendered using QML"
+ anchors.right: parent.right
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ anchors.margins: 20
+ }
+}
+//! [2]
diff --git a/examples/quick/scenegraph/vulkanunderqml/squircle.frag.spv b/examples/quick/scenegraph/vulkanunderqml/squircle.frag.spv
new file mode 100644
index 0000000000..e4d13a871d
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/squircle.frag.spv
Binary files differ
diff --git a/examples/quick/scenegraph/vulkanunderqml/squircle.vert.spv b/examples/quick/scenegraph/vulkanunderqml/squircle.vert.spv
new file mode 100644
index 0000000000..5df94a47e4
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/squircle.vert.spv
Binary files differ
diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp
new file mode 100644
index 0000000000..21f46a25c1
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+#include "vulkansquircle.h"
+#include <QtCore/QRunnable>
+#include <QtQuick/QQuickWindow>
+
+#include <QVulkanInstance>
+#include <QVulkanFunctions>
+
+class SquircleRenderer : public QObject
+{
+ Q_OBJECT
+public:
+ ~SquircleRenderer();
+
+ void setT(qreal t) { m_t = t; }
+ void setViewportSize(const QSize &size) { m_viewportSize = size; }
+ void setWindow(QQuickWindow *window) { m_window = window; }
+
+public slots:
+ void frameStart();
+ void mainPassRecordingStart();
+
+private:
+ enum Stage {
+ VertexStage,
+ FragmentStage
+ };
+ void prepareShader(Stage stage);
+ void init(int framesInFlight);
+
+ QSize m_viewportSize;
+ qreal m_t = 0;
+ QQuickWindow *m_window;
+
+ QByteArray m_vert;
+ QByteArray m_frag;
+
+ bool m_initialized = false;
+ VkPhysicalDevice m_physDev = VK_NULL_HANDLE;
+ VkDevice m_dev = VK_NULL_HANDLE;
+ QVulkanDeviceFunctions *m_devFuncs = nullptr;
+ QVulkanFunctions *m_funcs = nullptr;
+
+ VkBuffer m_vbuf = VK_NULL_HANDLE;
+ VkDeviceMemory m_vbufMem = VK_NULL_HANDLE;
+ VkBuffer m_ubuf = VK_NULL_HANDLE;
+ VkDeviceMemory m_ubufMem = VK_NULL_HANDLE;
+ VkDeviceSize m_allocPerUbuf = 0;
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+
+ VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
+ VkDescriptorSetLayout m_resLayout = VK_NULL_HANDLE;
+ VkPipeline m_pipeline = VK_NULL_HANDLE;
+
+ VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
+ VkDescriptorSet m_ubufDescriptor = VK_NULL_HANDLE;
+};
+
+VulkanSquircle::VulkanSquircle()
+{
+ connect(this, &QQuickItem::windowChanged, this, &VulkanSquircle::handleWindowChanged);
+}
+
+void VulkanSquircle::setT(qreal t)
+{
+ if (t == m_t)
+ return;
+ m_t = t;
+ emit tChanged();
+ if (window())
+ window()->update();
+}
+
+void VulkanSquircle::handleWindowChanged(QQuickWindow *win)
+{
+ if (win) {
+ connect(win, &QQuickWindow::beforeSynchronizing, this, &VulkanSquircle::sync, Qt::DirectConnection);
+ connect(win, &QQuickWindow::sceneGraphInvalidated, this, &VulkanSquircle::cleanup, Qt::DirectConnection);
+
+ // Ensure we start with cleared to black. The squircle's blend mode relies on this.
+ win->setColor(Qt::black);
+ }
+}
+
+// The safe way to release custom graphics resources is to both connect to
+// sceneGraphInvalidated() and implement releaseResources(). To support
+// threaded render loops the latter performs the SquircleRenderer destruction
+// via scheduleRenderJob(). Note that the VulkanSquircle may be gone by the time
+// the QRunnable is invoked.
+
+void VulkanSquircle::cleanup()
+{
+ delete m_renderer;
+ m_renderer = nullptr;
+}
+
+class CleanupJob : public QRunnable
+{
+public:
+ CleanupJob(SquircleRenderer *renderer) : m_renderer(renderer) { }
+ void run() override { delete m_renderer; }
+private:
+ SquircleRenderer *m_renderer;
+};
+
+void VulkanSquircle::releaseResources()
+{
+ window()->scheduleRenderJob(new CleanupJob(m_renderer), QQuickWindow::BeforeSynchronizingStage);
+ m_renderer = nullptr;
+}
+
+SquircleRenderer::~SquircleRenderer()
+{
+ qDebug("cleanup");
+ if (!m_devFuncs)
+ return;
+
+ m_devFuncs->vkDestroyPipeline(m_dev, m_pipeline, nullptr);
+ m_devFuncs->vkDestroyPipelineLayout(m_dev, m_pipelineLayout, nullptr);
+ m_devFuncs->vkDestroyDescriptorSetLayout(m_dev, m_resLayout, nullptr);
+
+ m_devFuncs->vkDestroyDescriptorPool(m_dev, m_descriptorPool, nullptr);
+
+ m_devFuncs->vkDestroyPipelineCache(m_dev, m_pipelineCache, nullptr);
+
+ m_devFuncs->vkDestroyBuffer(m_dev, m_vbuf, nullptr);
+ m_devFuncs->vkFreeMemory(m_dev, m_vbufMem, nullptr);
+
+ m_devFuncs->vkDestroyBuffer(m_dev, m_ubuf, nullptr);
+ m_devFuncs->vkFreeMemory(m_dev, m_ubufMem, nullptr);
+
+ qDebug("released");
+}
+
+void VulkanSquircle::sync()
+{
+ if (!m_renderer) {
+ m_renderer = new SquircleRenderer;
+ // Initializing resources is done before starting to record the
+ // renderpass, regardless of wanting an underlay or overlay.
+ connect(window(), &QQuickWindow::beforeRendering, m_renderer, &SquircleRenderer::frameStart, Qt::DirectConnection);
+ // Here we want an underlay and therefore connect to
+ // beforeRenderPassRecording. Changing to afterRenderPassRecording
+ // would render the squircle on top (overlay).
+ connect(window(), &QQuickWindow::beforeRenderPassRecording, m_renderer, &SquircleRenderer::mainPassRecordingStart, Qt::DirectConnection);
+ }
+ m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
+ m_renderer->setT(m_t);
+ m_renderer->setWindow(window());
+}
+
+void SquircleRenderer::frameStart()
+{
+ QSGRendererInterface *rif = m_window->rendererInterface();
+
+ // We are not prepared for anything other than running with the RHI and its Vulkan backend.
+ Q_ASSERT(rif->graphicsApi() == QSGRendererInterface::VulkanRhi);
+
+ if (m_vert.isEmpty())
+ prepareShader(VertexStage);
+ if (m_frag.isEmpty())
+ prepareShader(FragmentStage);
+
+ if (!m_initialized)
+ init(m_window->graphicsStateInfo().framesInFlight);
+}
+
+static const float vertices[] = {
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ 1, 1
+};
+
+const int UBUF_SIZE = 4;
+
+void SquircleRenderer::mainPassRecordingStart()
+{
+ // This example demonstrates the simple case: prepending some commands to
+ // the scenegraph's main renderpass. It does not create its own passes,
+ // rendertargets, etc. so no synchronization is needed.
+
+ const QQuickWindow::GraphicsStateInfo &stateInfo(m_window->graphicsStateInfo());
+ QSGRendererInterface *rif = m_window->rendererInterface();
+
+ VkDeviceSize ubufOffset = stateInfo.currentFrameSlot * m_allocPerUbuf;
+ void *p = nullptr;
+ VkResult err = m_devFuncs->vkMapMemory(m_dev, m_ubufMem, ubufOffset, m_allocPerUbuf, 0, &p);
+ if (err != VK_SUCCESS || !p)
+ qFatal("Failed to map uniform buffer memory: %d", err);
+ float t = m_t;
+ memcpy(p, &t, 4);
+ m_devFuncs->vkUnmapMemory(m_dev, m_ubufMem);
+
+ m_window->beginExternalCommands();
+
+ // Must query the command buffer _after_ beginExternalCommands(), this is
+ // actually important when running on Vulkan because what we get here is a
+ // new secondary command buffer, not the primary one.
+ VkCommandBuffer cb = *reinterpret_cast<VkCommandBuffer *>(
+ rif->getResource(m_window, QSGRendererInterface::CommandListResource));
+ Q_ASSERT(cb);
+
+ // Do not assume any state persists on the command buffer. (it may be a
+ // brand new one that just started recording)
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
+
+ VkDeviceSize vbufOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_vbuf, &vbufOffset);
+
+ uint32_t dynamicOffset = m_allocPerUbuf * stateInfo.currentFrameSlot;
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
+ &m_ubufDescriptor, 1, &dynamicOffset);
+
+ VkViewport vp = { 0, 0, float(m_viewportSize.width()), float(m_viewportSize.height()), 0.0f, 1.0f };
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &vp);
+ VkRect2D scissor = { { 0, 0 }, { uint32_t(m_viewportSize.width()), uint32_t(m_viewportSize.height()) } };
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0);
+
+ m_window->endExternalCommands();
+}
+
+void SquircleRenderer::prepareShader(Stage stage)
+{
+ QString filename;
+ if (stage == VertexStage) {
+ filename = QLatin1String(":/scenegraph/vulkanunderqml/squircle.vert.spv");
+ } else {
+ Q_ASSERT(stage == FragmentStage);
+ filename = QLatin1String(":/scenegraph/vulkanunderqml/squircle.frag.spv");
+ }
+ QFile f(filename);
+ if (!f.open(QIODevice::ReadOnly))
+ qFatal("Failed to read shader %s", qPrintable(filename));
+
+ const QByteArray contents = f.readAll();
+
+ if (stage == VertexStage) {
+ m_vert = contents;
+ Q_ASSERT(!m_vert.isEmpty());
+ } else {
+ m_frag = contents;
+ Q_ASSERT(!m_frag.isEmpty());
+ }
+}
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+void SquircleRenderer::init(int framesInFlight)
+{
+ qDebug("init");
+
+ Q_ASSERT(framesInFlight <= 3);
+ m_initialized = true;
+
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ QVulkanInstance *inst = reinterpret_cast<QVulkanInstance *>(
+ rif->getResource(m_window, QSGRendererInterface::VulkanInstanceResource));
+ Q_ASSERT(inst && inst->isValid());
+
+ m_physDev = *reinterpret_cast<VkPhysicalDevice *>(rif->getResource(m_window, QSGRendererInterface::PhysicalDeviceResource));
+ m_dev = *reinterpret_cast<VkDevice *>(rif->getResource(m_window, QSGRendererInterface::DeviceResource));
+ Q_ASSERT(m_physDev && m_dev);
+
+ m_devFuncs = inst->deviceFunctions(m_dev);
+ m_funcs = inst->functions();
+ Q_ASSERT(m_devFuncs && m_funcs);
+
+ VkRenderPass rp = *reinterpret_cast<VkRenderPass *>(
+ rif->getResource(m_window, QSGRendererInterface::RenderPassResource));
+ Q_ASSERT(rp);
+
+ // For simplicity we just use host visible buffers instead of device local + staging.
+
+ VkPhysicalDeviceProperties physDevProps;
+ m_funcs->vkGetPhysicalDeviceProperties(m_physDev, &physDevProps);
+
+ VkPhysicalDeviceMemoryProperties physDevMemProps;
+ m_funcs->vkGetPhysicalDeviceMemoryProperties(m_physDev, &physDevMemProps);
+
+ VkBufferCreateInfo bufferInfo;
+ memset(&bufferInfo, 0, sizeof(bufferInfo));
+ bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufferInfo.size = sizeof(vertices);
+ bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ VkResult err = m_devFuncs->vkCreateBuffer(m_dev, &bufferInfo, nullptr, &m_vbuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(m_dev, m_vbuf, &memReq);
+ VkMemoryAllocateInfo allocInfo;
+ memset(&allocInfo, 0, sizeof(allocInfo));
+ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.allocationSize = memReq.size;
+
+ uint32_t memTypeIndex = uint32_t(-1);
+ const VkMemoryType *memType = physDevMemProps.memoryTypes;
+ for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) {
+ if (memReq.memoryTypeBits & (1 << i)) {
+ if ((memType[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ && (memType[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
+ {
+ memTypeIndex = i;
+ break;
+ }
+ }
+ }
+ if (memTypeIndex == uint32_t(-1))
+ qFatal("Failed to find host visible and coherent memory type");
+
+ allocInfo.memoryTypeIndex = memTypeIndex;
+ err = m_devFuncs->vkAllocateMemory(m_dev, &allocInfo, nullptr, &m_vbufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate vertex buffer memory of size %u: %d", uint(allocInfo.allocationSize), err);
+
+ void *p = nullptr;
+ err = m_devFuncs->vkMapMemory(m_dev, m_vbufMem, 0, allocInfo.allocationSize, 0, &p);
+ if (err != VK_SUCCESS || !p)
+ qFatal("Failed to map vertex buffer memory: %d", err);
+ memcpy(p, vertices, sizeof(vertices));
+ m_devFuncs->vkUnmapMemory(m_dev, m_vbufMem);
+ err = m_devFuncs->vkBindBufferMemory(m_dev, m_vbuf, m_vbufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+
+ // Now have a uniform buffer with enough space for the buffer data for each
+ // (potentially) in-flight frame. (as we will write the contents every
+ // frame, and so would need to wait for command buffer completion if there
+ // was only one, and that would not be nice)
+
+ // Could have three buffers and three descriptor sets, or one buffer and
+ // one descriptor set and dynamic offset. We chose the latter in this
+ // example.
+
+ // We use one memory allocation for all uniform buffers, but then have to
+ // watch out for the buffer offset aligment requirement, which may be as
+ // large as 256 bytes.
+
+ m_allocPerUbuf = aligned(UBUF_SIZE, physDevProps.limits.minUniformBufferOffsetAlignment);
+
+ bufferInfo.size = framesInFlight * m_allocPerUbuf;
+ bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ err = m_devFuncs->vkCreateBuffer(m_dev, &bufferInfo, nullptr, &m_ubuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create uniform buffer: %d", err);
+ m_devFuncs->vkGetBufferMemoryRequirements(m_dev, m_ubuf, &memReq);
+ memTypeIndex = -1;
+ for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) {
+ if (memReq.memoryTypeBits & (1 << i)) {
+ if ((memType[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ && (memType[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
+ {
+ memTypeIndex = i;
+ break;
+ }
+ }
+ }
+ if (memTypeIndex == uint32_t(-1))
+ qFatal("Failed to find host visible and coherent memory type");
+
+ allocInfo.allocationSize = framesInFlight * m_allocPerUbuf;
+ allocInfo.memoryTypeIndex = memTypeIndex;
+ err = m_devFuncs->vkAllocateMemory(m_dev, &allocInfo, nullptr, &m_ubufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate uniform buffer memory of size %u: %d", uint(allocInfo.allocationSize), err);
+
+ err = m_devFuncs->vkBindBufferMemory(m_dev, m_ubuf, m_ubufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind uniform buffer memory: %d", err);
+
+ // Now onto the pipeline.
+
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ err = m_devFuncs->vkCreatePipelineCache(m_dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ VkDescriptorSetLayoutBinding descLayoutBinding;
+ memset(&descLayoutBinding, 0, sizeof(descLayoutBinding));
+ descLayoutBinding.binding = 0;
+ descLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ descLayoutBinding.descriptorCount = 1;
+ descLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
+ VkDescriptorSetLayoutCreateInfo layoutInfo;
+ memset(&layoutInfo, 0, sizeof(layoutInfo));
+ layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ layoutInfo.bindingCount = 1;
+ layoutInfo.pBindings = &descLayoutBinding;
+ err = m_devFuncs->vkCreateDescriptorSetLayout(m_dev, &layoutInfo, nullptr, &m_resLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_resLayout;
+ err = m_devFuncs->vkCreatePipelineLayout(m_dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
+ if (err != VK_SUCCESS)
+ qWarning("Failed to create pipeline layout: %d", err);
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = m_vert.size();
+ shaderInfo.pCode = reinterpret_cast<const quint32 *>(m_vert.constData());
+ VkShaderModule vertShaderModule;
+ err = m_devFuncs->vkCreateShaderModule(m_dev, &shaderInfo, nullptr, &vertShaderModule);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex shader module: %d", err);
+
+ shaderInfo.codeSize = m_frag.size();
+ shaderInfo.pCode = reinterpret_cast<const quint32 *>(m_frag.constData());
+ VkShaderModule fragShaderModule;
+ err = m_devFuncs->vkCreateShaderModule(m_dev, &shaderInfo, nullptr, &fragShaderModule);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create fragment shader module: %d", err);
+
+ VkPipelineShaderStageCreateInfo stageInfo[2];
+ memset(&stageInfo, 0, sizeof(stageInfo));
+ stageInfo[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ stageInfo[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
+ stageInfo[0].module = vertShaderModule;
+ stageInfo[0].pName = "main";
+ stageInfo[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ stageInfo[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+ stageInfo[1].module = fragShaderModule;
+ stageInfo[1].pName = "main";
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = stageInfo;
+
+ VkVertexInputBindingDescription vertexBinding = {
+ 0, // binding
+ 2 * sizeof(float), // stride
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttr = {
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32_SFLOAT, // 'vertices' only has 2 floats per vertex
+ 0 // offset
+ };
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ memset(&vertexInputInfo, 0, sizeof(vertexInputInfo));
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBinding;
+ vertexInputInfo.vertexAttributeDescriptionCount = 1;
+ vertexInputInfo.pVertexAttributeDescriptions = &vertexAttr;
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkDynamicState dynStates[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dynamicInfo;
+ memset(&dynamicInfo, 0, sizeof(dynamicInfo));
+ dynamicInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dynamicInfo.dynamicStateCount = 2;
+ dynamicInfo.pDynamicStates = dynStates;
+ pipelineInfo.pDynamicState = &dynamicInfo;
+
+ VkPipelineViewportStateCreateInfo viewportInfo;
+ memset(&viewportInfo, 0, sizeof(viewportInfo));
+ viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ viewportInfo.viewportCount = viewportInfo.scissorCount = 1;
+ pipelineInfo.pViewportState = &viewportInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo iaInfo;
+ memset(&iaInfo, 0, sizeof(iaInfo));
+ iaInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ iaInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pipelineInfo.pInputAssemblyState = &iaInfo;
+
+ VkPipelineRasterizationStateCreateInfo rsInfo;
+ memset(&rsInfo, 0, sizeof(rsInfo));
+ rsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rsInfo.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rsInfo;
+
+ VkPipelineMultisampleStateCreateInfo msInfo;
+ memset(&msInfo, 0, sizeof(msInfo));
+ msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ msInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ pipelineInfo.pMultisampleState = &msInfo;
+
+ VkPipelineDepthStencilStateCreateInfo dsInfo;
+ memset(&dsInfo, 0, sizeof(dsInfo));
+ dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ pipelineInfo.pDepthStencilState = &dsInfo;
+
+ // SrcAlpha, One
+ VkPipelineColorBlendStateCreateInfo blendInfo;
+ memset(&blendInfo, 0, sizeof(blendInfo));
+ blendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ VkPipelineColorBlendAttachmentState blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.blendEnable = true;
+ blend.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
+ blend.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
+ blend.colorBlendOp = VK_BLEND_OP_ADD;
+ blend.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
+ blend.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ blend.alphaBlendOp = VK_BLEND_OP_ADD;
+ blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT
+ | VK_COLOR_COMPONENT_A_BIT;
+ blendInfo.attachmentCount = 1;
+ blendInfo.pAttachments = &blend;
+ pipelineInfo.pColorBlendState = &blendInfo;
+
+ pipelineInfo.layout = m_pipelineLayout;
+
+ pipelineInfo.renderPass = rp;
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(m_dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
+
+ m_devFuncs->vkDestroyShaderModule(m_dev, vertShaderModule, nullptr);
+ m_devFuncs->vkDestroyShaderModule(m_dev, fragShaderModule, nullptr);
+
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+
+ // Now just need some descriptors.
+ VkDescriptorPoolSize descPoolSizes[] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1 }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.flags = 0; // won't use vkFreeDescriptorSets
+ descPoolInfo.maxSets = 1;
+ descPoolInfo.poolSizeCount = sizeof(descPoolSizes) / sizeof(descPoolSizes[0]);
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ err = m_devFuncs->vkCreateDescriptorPool(m_dev, &descPoolInfo, nullptr, &m_descriptorPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetAllocateInfo descAllocInfo;
+ memset(&descAllocInfo, 0, sizeof(descAllocInfo));
+ descAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ descAllocInfo.descriptorPool = m_descriptorPool;
+ descAllocInfo.descriptorSetCount = 1;
+ descAllocInfo.pSetLayouts = &m_resLayout;
+ err = m_devFuncs->vkAllocateDescriptorSets(m_dev, &descAllocInfo, &m_ubufDescriptor);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set");
+
+ VkWriteDescriptorSet writeInfo;
+ memset(&writeInfo, 0, sizeof(writeInfo));
+ writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ writeInfo.dstSet = m_ubufDescriptor;
+ writeInfo.dstBinding = 0;
+ writeInfo.descriptorCount = 1;
+ writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ VkDescriptorBufferInfo bufInfo;
+ bufInfo.buffer = m_ubuf;
+ bufInfo.offset = 0; // dynamic offset is used so this is ignored
+ bufInfo.range = UBUF_SIZE;
+ writeInfo.pBufferInfo = &bufInfo;
+ m_devFuncs->vkUpdateDescriptorSets(m_dev, 1, &writeInfo, 0, nullptr);
+}
+
+#include "vulkansquircle.moc"
diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h
new file mode 100644
index 0000000000..7e65d01a15
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+#ifndef VULKANSQUIRCLE_H
+#define VULKANSQUIRCLE_H
+
+#include <QtQuick/QQuickItem>
+
+class SquircleRenderer;
+
+class VulkanSquircle : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
+
+public:
+ VulkanSquircle();
+
+ qreal t() const { return m_t; }
+ void setT(qreal t);
+
+signals:
+ void tChanged();
+
+public slots:
+ void sync();
+ void cleanup();
+
+private slots:
+ void handleWindowChanged(QQuickWindow *win);
+
+private:
+ void releaseResources() override;
+
+ qreal m_t = 0;
+ SquircleRenderer *m_renderer = nullptr;
+};
+
+#endif
diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro
new file mode 100644
index 0000000000..9ea57b91c3
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro
@@ -0,0 +1,10 @@
+!qtConfig(vulkan): error("This example requires Qt built with Vulkan support")
+
+QT += qml quick
+
+HEADERS += vulkansquircle.h
+SOURCES += vulkansquircle.cpp main.cpp
+RESOURCES += vulkanunderqml.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/vulkanunderqml
+INSTALLS += target
diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.qrc b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.qrc
new file mode 100644
index 0000000000..c85be0f238
--- /dev/null
+++ b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/scenegraph/vulkanunderqml">
+ <file>main.qml</file>
+ <file>squircle.vert.spv</file>
+ <file>squircle.frag.spv</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/shapes/content/interactive.qml b/examples/quick/shapes/content/interactive.qml
index 55a1d16299..78413db3f9 100644
--- a/examples/quick/shapes/content/interactive.qml
+++ b/examples/quick/shapes/content/interactive.qml
@@ -170,14 +170,45 @@ Rectangle {
property variant resizers: []
property variant funcs
+ property Component mouseArea: Component {
+ Rectangle {
+ id: rr
+
+ property variant obj
+ property string xprop
+ property string yprop
+
+ width: 20
+ height: 20
+
+ MouseArea {
+ property bool a: false
+
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: color = "yellow"
+ onExited: color = rr.color
+ onPressed: a = true
+ onReleased: a = false
+ onPositionChanged: {
+ if (a) {
+ var pt = mapToItem(rr.parent, mouse.x, mouse.y);
+ rr.obj[rr.xprop] = pt.x
+ rr.obj[rr.yprop] = pt.y
+ rr.x = pt.x - 10
+ rr.y = pt.y - 10
+ }
+ }
+ }
+ }
+ }
+
function genResizer(obj, x, y, xprop, yprop, color) {
- var ma = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; Rectangle { id: rr; property variant obj; color: "' + color + '"; width: 20; height: 20;'+
- 'MouseArea { anchors.fill: parent; hoverEnabled: true;' +
- 'onEntered: color = "yellow"; onExited: color = "' + color + '";' +
- 'property bool a: false; onPressed: a = true; onReleased: a = false; ' +
- 'onPositionChanged: if (a) { var pt = mapToItem(rr.parent, mouse.x, mouse.y);' +
- 'obj.' + xprop + ' = pt.x; obj.' + yprop + ' = pt.y; rr.x = pt.x - 10; rr.y = pt.y - 10; } } }',
- canvas, "resizer_item");
+ var ma = mouseArea.createObject(canvas, {
+ color: color,
+ xprop: xprop,
+ yprop: yprop
+ });
ma.visible = root.showResizers;
ma.obj = obj;
ma.x = x - 10;
@@ -186,15 +217,55 @@ Rectangle {
return ma;
}
+ property Component linePath: Component {
+ ShapePath {
+ id: lineShapePath
+ strokeColor: "black"
+ strokeWidth: widthSlider.value
+ fillColor: "transparent"
+ PathLine {
+ x: lineShapePath.startX + 1
+ y: lineShapePath.startY + 1
+ }
+ }
+ }
+
+ property Component cubicPath: Component {
+ ShapePath {
+ id: cubicShapePath
+ strokeColor: "black"
+ strokeWidth: widthSlider.value
+ fillColor: root.fill ? 'green' : 'transparent'
+ PathCubic {
+ x: cubicShapePath.startX + 1
+ y: cubicShapePath.startY + 1
+ control1X: cubicShapePath.startX + 50;
+ control1Y: cubicShapePath.startY + 50;
+ control2X: cubicShapePath.startX + 150;
+ control2Y: cubicShapePath.startY + 50;
+ }
+ }
+ }
+
+ property Component quadPath: Component {
+ ShapePath {
+ id: quadShapePath
+ strokeColor: "black"
+ strokeWidth: widthSlider.value
+ fillColor: root.fill ? 'green' : 'transparent'
+ PathQuad {
+ x: quadShapePath.startx + 1
+ y: quadShapePath.startY + 1
+ controlX: quadShapePath.startX + 50
+ controlY: quadShapePath.startY + 50
+ }
+ }
+ }
+
Component.onCompleted: {
funcs = [
{ "start": function(x, y) {
- var p = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; ShapePath {' +
- 'strokeColor: "black"; fillColor: "transparent";'+
- 'strokeWidth: ' + widthSlider.value + ';' +
- 'startX: ' + x + '; startY: ' + y + ';' +
- 'PathLine { x: ' + x + ' + 1; y: ' + y + ' + 1 } }',
- root, "dynamic_visual_path");
+ var p = linePath.createObject(root, { startX: x, startY: y });
shape.data.push(p);
activePath = p;
}, "move": function(x, y) {
@@ -211,13 +282,7 @@ Rectangle {
}
},
{ "start": function(x, y) {
- var p = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; ShapePath {' +
- 'strokeColor: "black"; fillColor: "' + (root.fill ? 'green' : 'transparent') + '";'+
- 'strokeWidth: ' + widthSlider.value + ';' +
- 'startX: ' + x + '; startY: ' + y + ';' +
- 'PathCubic { x: ' + x + ' + 1; y: ' + y + ' + 1;' +
- 'control1X: ' + x + ' + 50; control1Y: ' + y + ' + 50; control2X: ' + x + ' + 150; control2Y: ' + y + ' + 50; } }',
- root, "dynamic_visual_path");
+ var p = cubicPath.createObject(root, { startX: x, startY: y });
shape.data.push(p);
activePath = p;
}, "move": function(x, y) {
@@ -236,13 +301,7 @@ Rectangle {
}
},
{ "start": function(x, y) {
- var p = Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; ShapePath {' +
- 'strokeColor: "black"; fillColor: "' + (root.fill ? 'green' : 'transparent') + '";'+
- 'strokeWidth: ' + widthSlider.value + ';' +
- 'startX: ' + x + '; startY: ' + y + ';' +
- 'PathQuad { x: ' + x + ' + 1; y: ' + y + ' + 1;' +
- 'controlX: ' + x + ' + 50; controlY: ' + y + ' + 50 } }',
- root, "dynamic_visual_path");
+ var p = quadPath.createObject(root, { startX: x, startY: y });
shape.data.push(p);
activePath = p;
}, "move": function(x, y) {
diff --git a/examples/quick/tableview/gameoflife/gameoflifemodel.h b/examples/quick/tableview/gameoflife/gameoflifemodel.h
index 3ea1469861..161e0b2cfc 100644
--- a/examples/quick/tableview/gameoflife/gameoflifemodel.h
+++ b/examples/quick/tableview/gameoflife/gameoflifemodel.h
@@ -54,11 +54,13 @@
#include <array>
#include <QAbstractTableModel>
#include <QPoint>
+#include <QtQml/qqml.h>
//! [modelclass]
class GameOfLifeModel : public QAbstractTableModel
{
Q_OBJECT
+ QML_ELEMENT
Q_ENUMS(Roles)
public:
diff --git a/examples/quick/tableview/gameoflife/main.cpp b/examples/quick/tableview/gameoflife/main.cpp
index 5101880b06..fcea7080ea 100644
--- a/examples/quick/tableview/gameoflife/main.cpp
+++ b/examples/quick/tableview/gameoflife/main.cpp
@@ -59,7 +59,7 @@ int main(int argc, char *argv[])
QQmlApplicationEngine engine;
//! [registertype]
- qmlRegisterType<GameOfLifeModel>("GameOfLifeModel", 1, 0, "GameOfLifeModel");
+ qmlRegisterTypesAndRevisions<GameOfLifeModel>("GameOfLifeModel", 1);
//! [registertype]
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
diff --git a/examples/quick/tableview/pixelator/imagemodel.h b/examples/quick/tableview/pixelator/imagemodel.h
index bf0ec90da4..de8ad7cd8d 100644
--- a/examples/quick/tableview/pixelator/imagemodel.h
+++ b/examples/quick/tableview/pixelator/imagemodel.h
@@ -53,12 +53,14 @@
#include <QAbstractTableModel>
#include <QImage>
+#include <QtQml/qqml.h>
//! [model]
class ImageModel : public QAbstractTableModel
{
Q_OBJECT
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+ QML_ELEMENT
public:
ImageModel(QObject *parent = nullptr);
diff --git a/examples/quick/tableview/pixelator/main.cpp b/examples/quick/tableview/pixelator/main.cpp
index c57039556a..a8cb6c4e86 100644
--- a/examples/quick/tableview/pixelator/main.cpp
+++ b/examples/quick/tableview/pixelator/main.cpp
@@ -60,7 +60,7 @@ int main(int argc, char *argv[])
QQmlApplicationEngine engine;
//! [registertype]
- qmlRegisterType<ImageModel>("ImageModel", 1, 0, "ImageModel");
+ qmlRegisterTypesAndRevisions<ImageModel>("ImageModel", 1);
//! [registertype]
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
diff --git a/examples/quick/views/doc/src/views.qdoc b/examples/quick/views/doc/src/views.qdoc
index 294b88542b..16237a68e0 100644
--- a/examples/quick/views/doc/src/views.qdoc
+++ b/examples/quick/views/doc/src/views.qdoc
@@ -87,7 +87,7 @@
\section1 Packages
- \e Packages uses the \l Package type to transition delegates between
+ \e Packages use the \l [QML]{Package} type to transition delegates between
two views.
It has a Package object which defines delegate items for each view and an
diff --git a/src/imports/builtins/builtins.qmltypes b/src/imports/builtins/builtins.qmltypes
index c783c63caf..765c92fcb9 100644
--- a/src/imports/builtins/builtins.qmltypes
+++ b/src/imports/builtins/builtins.qmltypes
@@ -1685,6 +1685,17 @@ Module {
"ChecksumItuV41": 1
}
}
+ Enum {
+ name: "HighDpiScaleFactorRoundingPolicy"
+ values: {
+ "Unset": 0,
+ "Round": 1,
+ "Ceil": 2,
+ "Floor": 3,
+ "RoundPreferFloor": 4,
+ "PassThrough": 5
+ }
+ }
}
Component { name: "QEasingCurve"; prototype: "QQmlEasingValueType" }
}
diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp
index 40968d5e1d..cbe4f9353d 100644
--- a/src/imports/folderlistmodel/plugin.cpp
+++ b/src/imports/folderlistmodel/plugin.cpp
@@ -55,18 +55,13 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.folderlistmodel"));
- qmlRegisterType<QQuickFolderListModel>(uri,1,0,"FolderListModel");
- qmlRegisterType<QQuickFolderListModel>(uri,2,0,"FolderListModel");
- qmlRegisterType<QQuickFolderListModel,1>(uri,2,1,"FolderListModel");
- qmlRegisterType<QQuickFolderListModel,2>(uri,2,2,"FolderListModel");
- qmlRegisterModule(uri, 2, 15);
+ // Major version 1 only has a single revision, 0.
+ qmlRegisterType<QQuickFolderListModel>(uri, 1, 0, "FolderListModel");
- // revision in Qt 5.11: added status property
- qmlRegisterType<QQuickFolderListModel,11>(uri, 2, 11, "FolderListModel");
+ qmlRegisterTypesAndRevisions<QQuickFolderListModel>(uri, 2);
- // revision in Qt 5.12: added sortCaseSensitive property
- qmlRegisterType<QQuickFolderListModel,12>(uri, 2, 12, "FolderListModel");
+ qmlRegisterModule(uri, 2, 15);
}
};
//![class decl]
diff --git a/src/imports/folderlistmodel/plugins.qmltypes b/src/imports/folderlistmodel/plugins.qmltypes
index 0fdbae66d3..7c53c99665 100644
--- a/src/imports/folderlistmodel/plugins.qmltypes
+++ b/src/imports/folderlistmodel/plugins.qmltypes
@@ -9,6 +9,280 @@ import QtQuick.tooling 1.2
Module {
dependencies: ["QtQuick 2.0"]
Component {
+ name: "QAbstractItemModel"
+ prototype: "QObject"
+ Enum {
+ name: "LayoutChangeHint"
+ values: {
+ "NoLayoutChangeHint": 0,
+ "VerticalSortHint": 1,
+ "HorizontalSortHint": 2
+ }
+ }
+ Enum {
+ name: "CheckIndexOption"
+ values: {
+ "NoOption": 0,
+ "IndexIsValid": 1,
+ "DoNotUseParent": 2,
+ "ParentIsInvalid": 4
+ }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ Parameter { name: "roles"; type: "QVector<int>" }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "headerDataChanged"
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutChanged" }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutAboutToBeChanged" }
+ Signal {
+ name: "rowsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal { name: "modelAboutToBeReset" }
+ Signal { name: "modelReset" }
+ Signal {
+ name: "rowsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationRow"; type: "int" }
+ }
+ Signal {
+ name: "rowsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "row"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationColumn"; type: "int" }
+ }
+ Signal {
+ name: "columnsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method { name: "submit"; type: "bool" }
+ Method { name: "revert" }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "parent"
+ type: "QModelIndex"
+ Parameter { name: "child"; type: "QModelIndex" }
+ }
+ Method {
+ name: "sibling"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "idx"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "rowCount"; type: "int" }
+ Method {
+ name: "columnCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "columnCount"; type: "int" }
+ Method {
+ name: "hasChildren"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "hasChildren"; type: "bool" }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ }
+ Method {
+ name: "fetchMore"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "canFetchMore"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "flags"
+ type: "Qt::ItemFlags"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ Parameter { name: "flags"; type: "Qt::MatchFlags" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ }
+ Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
+ Component {
name: "QQuickFolderListModel"
prototype: "QAbstractListModel"
exports: [
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index affb1e9fe2..f5acfd86b7 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -539,6 +539,8 @@ QStringList QQuickFolderListModel::nameFilters() const
void QQuickFolderListModel::setNameFilters(const QStringList &filters)
{
Q_D(QQuickFolderListModel);
+ if (d->nameFilters == filters)
+ return;
d->fileInfoThread.setNameFilters(filters);
d->nameFilters = filters;
}
@@ -731,6 +733,7 @@ void QQuickFolderListModel::setShowDotAndDotDot(bool on)
if (on != d->showDotAndDotDot) {
d->fileInfoThread.setShowDotAndDotDot(on);
+ d->showDotAndDotDot = on;
}
}
@@ -756,6 +759,7 @@ void QQuickFolderListModel::setShowHidden(bool on)
if (on != d->showHidden) {
d->fileInfoThread.setShowHidden(on);
+ d->showHidden = on;
}
}
@@ -781,6 +785,7 @@ void QQuickFolderListModel::setShowOnlyReadable(bool on)
if (on != d->showOnlyReadable) {
d->fileInfoThread.setShowOnlyReadable(on);
+ d->showOnlyReadable = on;
}
}
@@ -805,6 +810,7 @@ void QQuickFolderListModel::setCaseSensitive(bool on)
if (on != d->caseSensitive) {
d->fileInfoThread.setCaseSensitive(on);
+ d->caseSensitive = on;
}
}
@@ -852,7 +858,7 @@ QQuickFolderListModel::Status QQuickFolderListModel::status() const
\qmlproperty bool FolderListModel::sortCaseSensitive
\since 5.12
- If set to true, the sort is case sensitive. This property is true by default.
+ If set to \c true, the sort is case sensitive. This property is \c true by default.
*/
bool QQuickFolderListModel::sortCaseSensitive() const
@@ -874,8 +880,8 @@ void QQuickFolderListModel::setSortCaseSensitive(bool on)
/*!
\qmlmethod var FolderListModel::get(int index, string property)
- Get the folder property for the given index. The following properties
- are available.
+ Returns the folder \a property for the given \a index. The following properties
+ are available:
\list
\li \c fileName
@@ -902,7 +908,7 @@ QVariant QQuickFolderListModel::get(int idx, const QString &property) const
\qmlmethod int FolderListModel::indexOf(url file)
\since 5.6
- Get the index of the given file URL if the model contains it,
+ Returns the index of the given \a file URL if the model contains it,
or -1 if not.
*/
int QQuickFolderListModel::indexOf(const QUrl &file) const
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h
index d93e7daf3f..5897bd2e0f 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.h
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h
@@ -79,6 +79,7 @@ class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus
Q_PROPERTY(bool sortCaseSensitive READ sortCaseSensitive WRITE setSortCaseSensitive REVISION 12)
//![class props]
+ QML_NAMED_ELEMENT(FolderListModel)
//![abslistmodel]
public:
QQuickFolderListModel(QObject *parent = nullptr);
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index a87b0a59f6..9973883024 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -28,6 +28,6 @@ qtHaveModule(quick) {
qtConfig(quick-particles): \
SUBDIRS += particles
- qtConfig(quick-path):qtConfig(thread): SUBDIRS += shapes
+ qtConfig(quick-path): SUBDIRS += shapes
}
diff --git a/src/imports/labsanimation/labsanimation.pro b/src/imports/labsanimation/labsanimation.pro
index 64e076401f..128bc28ddb 100644
--- a/src/imports/labsanimation/labsanimation.pro
+++ b/src/imports/labsanimation/labsanimation.pro
@@ -4,8 +4,12 @@ TARGETPATH = Qt/labs/animation
IMPORT_VERSION = 1.0
SOURCES += \
+ qquickboundaryrule.cpp \
plugin.cpp
+HEADERS += \
+ qquickboundaryrule_p.h
+
QT = qml-private quick-private
load(qml_plugin)
diff --git a/src/imports/labsanimation/plugin.cpp b/src/imports/labsanimation/plugin.cpp
index d8c0c071ca..a74a30663a 100644
--- a/src/imports/labsanimation/plugin.cpp
+++ b/src/imports/labsanimation/plugin.cpp
@@ -40,7 +40,7 @@
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
-#include <private/qquickboundaryrule_p.h>
+#include "qquickboundaryrule_p.h"
QT_BEGIN_NAMESPACE
@@ -70,7 +70,7 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.animation"));
- qmlRegisterType<QQuickBoundaryRule>(uri, 1, 0, "BoundaryRule");
+ qmlRegisterTypesAndRevisions<QQuickBoundaryRule>(uri, 1);
qmlRegisterModule(uri, 1, 0);
}
};
diff --git a/src/imports/labsanimation/plugins.qmltypes b/src/imports/labsanimation/plugins.qmltypes
index 065e65ad7a..2ecc5e6f5d 100644
--- a/src/imports/labsanimation/plugins.qmltypes
+++ b/src/imports/labsanimation/plugins.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt.labs.animation 1.0'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt.labs.animation 1.0'
Module {
- dependencies: ["QtQuick 2.0"]
+ dependencies: []
Component {
name: "QQuickBoundaryRule"
prototype: "QObject"
diff --git a/src/quick/util/qquickboundaryrule.cpp b/src/imports/labsanimation/qquickboundaryrule.cpp
index 3558c8bfa0..3558c8bfa0 100644
--- a/src/quick/util/qquickboundaryrule.cpp
+++ b/src/imports/labsanimation/qquickboundaryrule.cpp
diff --git a/src/quick/util/qquickboundaryrule_p.h b/src/imports/labsanimation/qquickboundaryrule_p.h
index 3325b675c5..1681558304 100644
--- a/src/quick/util/qquickboundaryrule_p.h
+++ b/src/imports/labsanimation/qquickboundaryrule_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
class QQuickAbstractAnimation;
class QQuickBoundaryRulePrivate;
-class Q_QUICK_PRIVATE_EXPORT QQuickBoundaryRule : public QObject, public QQmlPropertyValueInterceptor
+class QQuickBoundaryRule : public QObject, public QQmlPropertyValueInterceptor
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickBoundaryRule)
@@ -77,6 +77,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBoundaryRule : public QObject, public QQmlPro
Q_PROPERTY(OvershootFilter overshootFilter READ overshootFilter WRITE setOvershootFilter NOTIFY overshootFilterChanged)
Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
Q_PROPERTY(int returnDuration READ returnDuration WRITE setReturnDuration NOTIFY returnDurationChanged)
+ QML_NAMED_ELEMENT(BoundaryRule)
public:
enum OvershootFilter {
diff --git a/src/imports/layouts/plugin.cpp b/src/imports/layouts/plugin.cpp
index 03a2c8fd00..28592213a8 100644
--- a/src/imports/layouts/plugin.cpp
+++ b/src/imports/layouts/plugin.cpp
@@ -57,15 +57,8 @@ public:
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Layouts"));
- qmlRegisterType<QQuickRowLayout>(uri, 1, 0, "RowLayout");
- qmlRegisterType<QQuickColumnLayout>(uri, 1, 0, "ColumnLayout");
- qmlRegisterType<QQuickGridLayout>(uri, 1, 0, "GridLayout");
- qmlRegisterType<QQuickStackLayout>(uri, 1, 3, "StackLayout");
- qmlRegisterUncreatableType<QQuickLayout>(uri, 1, 0, "Layout",
- QStringLiteral("Do not create objects of type Layout"));
- qmlRegisterUncreatableType<QQuickLayout>(uri, 1, 2, "Layout",
- QStringLiteral("Do not create objects of type Layout"));
- qmlRegisterRevision<QQuickGridLayoutBase, 1>(uri, 1, 1);
+ qmlRegisterTypesAndRevisions<QQuickRowLayout, QQuickColumnLayout, QQuickGridLayout,
+ QQuickStackLayout, QQuickLayout, QQuickGridLayoutBase>(uri, 1);
qmlRegisterModule(uri, 1, 15);
}
diff --git a/src/imports/layouts/plugins.qmltypes b/src/imports/layouts/plugins.qmltypes
index 6015164511..4ebef4ac51 100644
--- a/src/imports/layouts/plugins.qmltypes
+++ b/src/imports/layouts/plugins.qmltypes
@@ -12,15 +12,27 @@ Module {
name: "QQuickColumnLayout"
defaultProperty: "data"
prototype: "QQuickLinearLayout"
- exports: ["QtQuick.Layouts/ColumnLayout 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Layouts/ColumnLayout 1.0",
+ "QtQuick.Layouts/ColumnLayout 1.1",
+ "QtQuick.Layouts/ColumnLayout 1.11",
+ "QtQuick.Layouts/ColumnLayout 1.4",
+ "QtQuick.Layouts/ColumnLayout 1.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
}
Component {
name: "QQuickGridLayout"
defaultProperty: "data"
prototype: "QQuickGridLayoutBase"
- exports: ["QtQuick.Layouts/GridLayout 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Layouts/GridLayout 1.0",
+ "QtQuick.Layouts/GridLayout 1.1",
+ "QtQuick.Layouts/GridLayout 1.11",
+ "QtQuick.Layouts/GridLayout 1.4",
+ "QtQuick.Layouts/GridLayout 1.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "Flow"
values: {
@@ -45,9 +57,15 @@ Module {
name: "QQuickLayout"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick.Layouts/Layout 1.0", "QtQuick.Layouts/Layout 1.2"]
+ exports: [
+ "QtQuick.Layouts/Layout 1.0",
+ "QtQuick.Layouts/Layout 1.1",
+ "QtQuick.Layouts/Layout 1.11",
+ "QtQuick.Layouts/Layout 1.4",
+ "QtQuick.Layouts/Layout 1.7"
+ ]
isCreatable: false
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
attachedType: "QQuickLayoutAttached"
}
Component {
@@ -82,15 +100,26 @@ Module {
name: "QQuickRowLayout"
defaultProperty: "data"
prototype: "QQuickLinearLayout"
- exports: ["QtQuick.Layouts/RowLayout 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Layouts/RowLayout 1.0",
+ "QtQuick.Layouts/RowLayout 1.1",
+ "QtQuick.Layouts/RowLayout 1.11",
+ "QtQuick.Layouts/RowLayout 1.4",
+ "QtQuick.Layouts/RowLayout 1.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
}
Component {
name: "QQuickStackLayout"
defaultProperty: "data"
prototype: "QQuickLayout"
- exports: ["QtQuick.Layouts/StackLayout 1.3"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Layouts/StackLayout 1.11",
+ "QtQuick.Layouts/StackLayout 1.3",
+ "QtQuick.Layouts/StackLayout 1.4",
+ "QtQuick.Layouts/StackLayout 1.7"
+ ]
+ exportMetaObjectRevisions: [11, 3, 4, 7]
Property { name: "count"; type: "int"; isReadonly: true }
Property { name: "currentIndex"; type: "int" }
Method {
diff --git a/src/imports/layouts/qquicklayout_p.h b/src/imports/layouts/qquicklayout_p.h
index b31bffa290..c022a2fd47 100644
--- a/src/imports/layouts/qquicklayout_p.h
+++ b/src/imports/layouts/qquicklayout_p.h
@@ -61,6 +61,10 @@ class QQuickLayout : public QQuickItem, public QQuickItemChangeListener
{
Q_OBJECT
+ QML_NAMED_ELEMENT(Layout)
+ QML_UNCREATABLE("Do not create objects of type Layout.")
+ QML_ATTACHED(QQuickLayoutAttached)
+
public:
enum SizeHint {
MinimumSize = 0,
@@ -331,6 +335,5 @@ inline QQuickLayoutAttached *attachedLayoutObject(QQuickItem *item, bool create
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickLayout)
-QML_DECLARE_TYPEINFO(QQuickLayout, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKLAYOUT_P_H
diff --git a/src/imports/layouts/qquicklinearlayout_p.h b/src/imports/layouts/qquicklinearlayout_p.h
index 6706ebf9fa..634e51a048 100644
--- a/src/imports/layouts/qquicklinearlayout_p.h
+++ b/src/imports/layouts/qquicklinearlayout_p.h
@@ -57,6 +57,8 @@ class QQuickGridLayoutBase : public QQuickLayout
Q_OBJECT
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+ QML_ANONYMOUS
+ QML_ADDED_IN_MINOR_VERSION(1)
public:
@@ -140,6 +142,7 @@ class QQuickGridLayout : public QQuickGridLayoutBase
Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged)
Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+ QML_NAMED_ELEMENT(GridLayout)
public:
explicit QQuickGridLayout(QQuickItem *parent = 0);
qreal columnSpacing() const;
@@ -223,6 +226,7 @@ public:
class QQuickRowLayout : public QQuickLinearLayout
{
Q_OBJECT
+ QML_NAMED_ELEMENT(RowLayout)
public:
explicit QQuickRowLayout(QQuickItem *parent = 0)
@@ -238,6 +242,7 @@ public:
class QQuickColumnLayout : public QQuickLinearLayout
{
Q_OBJECT
+ QML_NAMED_ELEMENT(ColumnLayout)
public:
explicit QQuickColumnLayout(QQuickItem *parent = 0)
diff --git a/src/imports/layouts/qquickstacklayout.cpp b/src/imports/layouts/qquickstacklayout.cpp
index 116e162aa9..4c1d611409 100644
--- a/src/imports/layouts/qquickstacklayout.cpp
+++ b/src/imports/layouts/qquickstacklayout.cpp
@@ -94,7 +94,7 @@
\sa ColumnLayout
\sa GridLayout
\sa RowLayout
- \sa StackView
+ \sa {QtQuick.Controls::StackView}{StackView}
*/
QT_BEGIN_NAMESPACE
diff --git a/src/imports/layouts/qquickstacklayout_p.h b/src/imports/layouts/qquickstacklayout_p.h
index 46181c6f50..537d54900f 100644
--- a/src/imports/layouts/qquickstacklayout_p.h
+++ b/src/imports/layouts/qquickstacklayout_p.h
@@ -51,6 +51,8 @@ class QQuickStackLayout : public QQuickLayout
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ QML_NAMED_ELEMENT(StackLayout)
+ QML_ADDED_IN_MINOR_VERSION(3)
public:
explicit QQuickStackLayout(QQuickItem *parent = 0);
diff --git a/src/imports/localstorage/localstorage.pro b/src/imports/localstorage/localstorage.pro
index 5c8177e238..607a6cbbdd 100644
--- a/src/imports/localstorage/localstorage.pro
+++ b/src/imports/localstorage/localstorage.pro
@@ -5,7 +5,12 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT = sql qml-private core-private
-SOURCES += plugin.cpp
+SOURCES += \
+ plugin.cpp \
+ qquicklocalstorage.cpp
+
+HEADERS += \
+ qquicklocalstorage_p.h
load(qml_plugin)
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 740a394fa0..6366c51b47 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -36,781 +36,14 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include <QStringList>
+
+#include "qquicklocalstorage_p.h"
+
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
-#include <private/qqmlengine_p.h>
-#include <QDebug>
-#include <QtSql/qsqldatabase.h>
-#include <QtSql/qsqlquery.h>
-#include <QtSql/qsqlerror.h>
-#include <QtSql/qsqlrecord.h>
-#include <QtSql/qsqlfield.h>
-#include <QtCore/qstandardpaths.h>
-#include <QtCore/qstack.h>
-#include <QtCore/qcryptographichash.h>
-#include <QtCore/qsettings.h>
-#include <QtCore/qdir.h>
-#include <private/qv4sqlerrors_p.h>
-#include <private/qv4engine_p.h>
-#include <private/qv4object_p.h>
-#include <private/qv4functionobject_p.h>
-#include <private/qv4objectproto_p.h>
-#include <private/qv4scopedvalue_p.h>
-#include <private/qv4jscall_p.h>
-#include <private/qv4objectiterator_p.h>
QT_BEGIN_NAMESPACE
-#define V4THROW_SQL(error, desc) { \
- QV4::ScopedString v(scope, scope.engine->newString(desc)); \
- QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
- ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Value::fromInt32(error))); \
- scope.engine->throwError(ex); \
- RETURN_UNDEFINED(); \
-}
-
-#define V4THROW_SQL2(error, desc) { \
- QV4::ScopedString v(scope, scope.engine->newString(desc)); \
- QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
- ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Value::fromInt32(error))); \
- args->setReturnValue(scope.engine->throwError(ex)); \
- return; \
-}
-
-#define V4THROW_REFERENCE(string) { \
- QV4::ScopedString v(scope, scope.engine->newString(string)); \
- scope.engine->throwReferenceError(v); \
- RETURN_UNDEFINED(); \
-}
-
-
-class QQmlSqlDatabaseData : public QV4::ExecutionEngine::Deletable
-{
-public:
- QQmlSqlDatabaseData(QV4::ExecutionEngine *engine);
- ~QQmlSqlDatabaseData() override;
-
- QV4::PersistentValue databaseProto;
- QV4::PersistentValue queryProto;
- QV4::PersistentValue rowsProto;
-};
-
-V4_DEFINE_EXTENSION(QQmlSqlDatabaseData, databaseData)
-
-namespace QV4 {
-
-namespace Heap {
- struct QQmlSqlDatabaseWrapper : public Object {
- enum Type { Database, Query, Rows };
- void init()
- {
- Object::init();
- type = Database;
- database = new QSqlDatabase;
- version = new QString;
- sqlQuery = new QSqlQuery;
- }
-
- void destroy() {
- delete database;
- delete version;
- delete sqlQuery;
- Object::destroy();
- }
-
- Type type;
- QSqlDatabase *database;
-
- QString *version; // type == Database
-
- bool inTransaction; // type == Query
- bool readonly; // type == Query
-
- QSqlQuery *sqlQuery; // type == Rows
- bool forwardOnly; // type == Rows
- };
-}
-
-class QQmlSqlDatabaseWrapper : public Object
-{
-public:
- V4_OBJECT2(QQmlSqlDatabaseWrapper, Object)
- V4_NEEDS_DESTROY
-
- static Heap::QQmlSqlDatabaseWrapper *create(QV4::ExecutionEngine *engine)
- {
- return engine->memoryManager->allocate<QQmlSqlDatabaseWrapper>();
- }
-
- ~QQmlSqlDatabaseWrapper() {
- }
-
- static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
-};
-
-}
-
-using namespace QV4;
-
-DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
-
-
-
-static ReturnedValue qmlsqldatabase_version(const FunctionObject *b, const Value *thisObject, const QV4::Value *, int)
-{
- Scope scope(b);
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
- V4THROW_REFERENCE("Not a SQLDatabase object");
-
- RETURN_RESULT(Encode(scope.engine->newString(*r->d()->version)));
-}
-
-static ReturnedValue qmlsqldatabase_rows_length(const FunctionObject *b, const Value *thisObject, const QV4::Value *, int)
-{
- Scope scope(b);
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
- V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
-
- int s = r->d()->sqlQuery->size();
- if (s < 0) {
- // Inefficient
- if (r->d()->sqlQuery->last()) {
- s = r->d()->sqlQuery->at() + 1;
- } else {
- s = 0;
- }
- }
- RETURN_RESULT(Encode(s));
-}
-
-static ReturnedValue qmlsqldatabase_rows_forwardOnly(const FunctionObject *b, const Value *thisObject, const QV4::Value *, int)
-{
- Scope scope(b);
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
- V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
- RETURN_RESULT(Encode(r->d()->sqlQuery->isForwardOnly()));
-}
-
-static ReturnedValue qmlsqldatabase_rows_setForwardOnly(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
-{
- Scope scope(b);
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
- V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
- if (argc < 1)
- RETURN_RESULT(scope.engine->throwTypeError());
-
- r->d()->sqlQuery->setForwardOnly(argv[0].toBoolean());
- RETURN_UNDEFINED();
-}
-
-QQmlSqlDatabaseData::~QQmlSqlDatabaseData()
-{
-}
-
-static ReturnedValue qmlsqldatabase_rows_index(const QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = nullptr)
-{
- Scope scope(v4);
-
- if (r->d()->sqlQuery->at() == (int)index || r->d()->sqlQuery->seek(index)) {
- QSqlRecord record = r->d()->sqlQuery->record();
- // XXX optimize
- ScopedObject row(scope, v4->newObject());
- for (int ii = 0; ii < record.count(); ++ii) {
- QVariant v = record.value(ii);
- ScopedString s(scope, v4->newIdentifier(record.fieldName(ii)));
- ScopedValue val(scope, v.isNull() ? Encode::null() : v4->fromVariant(v));
- row->put(s.getPointer(), val);
- }
- if (hasProperty)
- *hasProperty = true;
- return row.asReturnedValue();
- } else {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
-}
-
-ReturnedValue QQmlSqlDatabaseWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
-{
- if (!id.isArrayIndex())
- return Object::virtualGet(m, id, receiver, hasProperty);
-
- uint index = id.asArrayIndex();
- Q_ASSERT(m->as<QQmlSqlDatabaseWrapper>());
- const QQmlSqlDatabaseWrapper *r = static_cast<const QQmlSqlDatabaseWrapper *>(m);
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
- return Object::virtualGet(m, id, receiver, hasProperty);
-
- return qmlsqldatabase_rows_index(r, r->engine(), index, hasProperty);
-}
-
-static ReturnedValue qmlsqldatabase_rows_item(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
-{
- Scope scope(b);
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
- V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
-
- RETURN_RESULT(qmlsqldatabase_rows_index(r, scope.engine, argc ? argv[0].toUInt32() : 0));
-}
-
-static QVariant toSqlVariant(QV4::ExecutionEngine *engine, const QV4::ScopedValue &value)
-{
- // toVariant() maps a null JS value to QVariant(VoidStar), but the SQL module
- // expects a null variant. (this is because of QTBUG-40880)
- if (value->isNull())
- return QVariant();
- return engine->toVariant(value, /*typehint*/-1);
-}
-
-static ReturnedValue qmlsqldatabase_executeSql(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
-{
- Scope scope(b);
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Query)
- V4THROW_REFERENCE("Not a SQLDatabase::Query object");
-
- if (!r->d()->inTransaction)
- V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,QQmlEngine::tr("executeSql called outside transaction()"));
-
- QSqlDatabase db = *r->d()->database;
-
- QString sql = argc ? argv[0].toQString() : QString();
-
- if (r->d()->readonly && !sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) {
- V4THROW_SQL(SQLEXCEPTION_SYNTAX_ERR, QQmlEngine::tr("Read-only Transaction"));
- }
-
- QSqlQuery query(db);
- bool err = false;
-
- ScopedValue result(scope, Value::undefinedValue());
-
- if (query.prepare(sql)) {
- if (argc > 1) {
- ScopedValue values(scope, argv[1]);
- if (values->as<ArrayObject>()) {
- ScopedArrayObject array(scope, values);
- quint32 size = array->getLength();
- QV4::ScopedValue v(scope);
- for (quint32 ii = 0; ii < size; ++ii) {
- query.bindValue(ii, toSqlVariant(scope.engine, (v = array->get(ii))));
- }
- } else if (values->as<Object>()) {
- ScopedObject object(scope, values);
- ObjectIterator it(scope, object, ObjectIterator::EnumerableOnly);
- ScopedValue key(scope);
- QV4::ScopedValue val(scope);
- while (1) {
- key = it.nextPropertyName(val);
- if (key->isNull())
- break;
- QVariant v = toSqlVariant(scope.engine, val);
- if (key->isString()) {
- query.bindValue(key->stringValue()->toQString(), v);
- } else {
- Q_ASSERT(key->isInteger());
- query.bindValue(key->integerValue(), v);
- }
- }
- } else {
- query.bindValue(0, toSqlVariant(scope.engine, values));
- }
- }
- if (query.exec()) {
- QV4::Scoped<QQmlSqlDatabaseWrapper> rows(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
- QV4::ScopedObject p(scope, databaseData(scope.engine)->rowsProto.value());
- rows->setPrototypeUnchecked(p.getPointer());
- rows->d()->type = Heap::QQmlSqlDatabaseWrapper::Rows;
- *rows->d()->database = db;
- *rows->d()->sqlQuery = query;
-
- ScopedObject resultObject(scope, scope.engine->newObject());
- result = resultObject.asReturnedValue();
- // XXX optimize
- ScopedString s(scope);
- ScopedValue v(scope);
- resultObject->put((s = scope.engine->newIdentifier("rowsAffected")).getPointer(), (v = Value::fromInt32(query.numRowsAffected())));
- resultObject->put((s = scope.engine->newIdentifier("insertId")).getPointer(), (v = scope.engine->newString(query.lastInsertId().toString())));
- resultObject->put((s = scope.engine->newIdentifier("rows")).getPointer(), rows);
- } else {
- err = true;
- }
- } else {
- err = true;
- }
- if (err)
- V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,query.lastError().text());
-
- RETURN_RESULT(result->asReturnedValue());
-}
-
-struct TransactionRollback {
- QSqlDatabase *db;
- bool *inTransactionFlag;
-
- TransactionRollback(QSqlDatabase *database, bool *transactionFlag)
- : db(database)
- , inTransactionFlag(transactionFlag)
- {
- if (inTransactionFlag)
- *inTransactionFlag = true;
- }
-
- ~TransactionRollback()
- {
- if (inTransactionFlag)
- *inTransactionFlag = false;
- if (db)
- db->rollback();
- }
-
- void clear() {
- db = nullptr;
- if (inTransactionFlag)
- *inTransactionFlag = false;
- inTransactionFlag = nullptr;
- }
-};
-
-
-static ReturnedValue qmlsqldatabase_changeVersion(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
-{
- Scope scope(b);
- if (argc < 2)
- RETURN_UNDEFINED();
-
- Scoped<QQmlSqlDatabaseWrapper> r(scope, *thisObject);
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
- V4THROW_REFERENCE("Not a SQLDatabase object");
-
- QSqlDatabase db = *r->d()->database;
- QString from_version = argv[0].toQString();
- QString to_version = argv[1].toQString();
- ScopedFunctionObject callback(scope, argc > 2 ? argv[2] : Value::undefinedValue());
-
- if (from_version != *r->d()->version)
- V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(*r->d()->version));
-
- bool ok = true;
- if (!!callback) {
- Scoped<QQmlSqlDatabaseWrapper> query(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
- ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
- query->setPrototypeUnchecked(p.getPointer());
- query->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
- *query->d()->database = db;
- *query->d()->version = *r->d()->version;
-
- ok = false;
- db.transaction();
-
- JSCallData jsCall(scope, 1);
- *jsCall->thisObject = scope.engine->globalObject;
- jsCall->args[0] = query;
-
- TransactionRollback rollbackOnException(&db, &query->d()->inTransaction);
- callback->call(jsCall);
- rollbackOnException.clear();
- if (!db.commit()) {
- db.rollback();
- V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR,QQmlEngine::tr("SQL transaction failed"));
- } else {
- ok = true;
- }
- }
-
- if (ok) {
- Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
- ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value());
- w->setPrototypeUnchecked(p.getPointer());
- w->d()->type = Heap::QQmlSqlDatabaseWrapper::Database;
- *w->d()->database = db;
- *w->d()->version = to_version;
-#if QT_CONFIG(settings)
- const QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(scope.engine->qmlEngine());
- QSettings ini(enginePrivate->offlineStorageDatabaseDirectory() + db.connectionName() + QLatin1String(".ini"), QSettings::IniFormat);
- ini.setValue(QLatin1String("Version"), to_version);
-#endif
- RETURN_RESULT(w.asReturnedValue());
- }
-
- RETURN_UNDEFINED();
-}
-
-static ReturnedValue qmlsqldatabase_transaction_shared(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc, bool readOnly)
-{
- Scope scope(b);
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
- V4THROW_REFERENCE("Not a SQLDatabase object");
-
- const FunctionObject *callback = argc ? argv[0].as<FunctionObject>() : nullptr;
- if (!callback)
- V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback"));
-
- QSqlDatabase db = *r->d()->database;
-
- Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
- QV4::ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
- w->setPrototypeUnchecked(p.getPointer());
- w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
- *w->d()->database = db;
- *w->d()->version = *r->d()->version;
- w->d()->readonly = readOnly;
-
- db.transaction();
- if (callback) {
- JSCallData jsCall(scope, 1);
- *jsCall->thisObject = scope.engine->globalObject;
- jsCall->args[0] = w;
- TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
- callback->call(jsCall);
- rollbackOnException.clear();
-
- if (!db.commit())
- db.rollback();
- }
-
- RETURN_UNDEFINED();
-}
-
-static ReturnedValue qmlsqldatabase_transaction(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
-{
- return qmlsqldatabase_transaction_shared(f, thisObject, argv, argc, false);
-}
-
-static ReturnedValue qmlsqldatabase_read_transaction(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
-{
- return qmlsqldatabase_transaction_shared(f, thisObject, argv, argc, true);
-}
-
-QQmlSqlDatabaseData::QQmlSqlDatabaseData(ExecutionEngine *v4)
-{
- Scope scope(v4);
- {
- ScopedObject proto(scope, v4->newObject());
- proto->defineDefaultProperty(QStringLiteral("transaction"), qmlsqldatabase_transaction);
- proto->defineDefaultProperty(QStringLiteral("readTransaction"), qmlsqldatabase_read_transaction);
- proto->defineAccessorProperty(QStringLiteral("version"), qmlsqldatabase_version, nullptr);
- proto->defineDefaultProperty(QStringLiteral("changeVersion"), qmlsqldatabase_changeVersion);
- databaseProto = proto;
- }
-
- {
- ScopedObject proto(scope, v4->newObject());
- proto->defineDefaultProperty(QStringLiteral("executeSql"), qmlsqldatabase_executeSql);
- queryProto = proto;
- }
- {
- ScopedObject proto(scope, v4->newObject());
- proto->defineDefaultProperty(QStringLiteral("item"), qmlsqldatabase_rows_item);
- proto->defineAccessorProperty(QStringLiteral("length"), qmlsqldatabase_rows_length, nullptr);
- proto->defineAccessorProperty(QStringLiteral("forwardOnly"),
- qmlsqldatabase_rows_forwardOnly, qmlsqldatabase_rows_setForwardOnly);
- rowsProto = proto;
- }
-}
-
-/*
-HTML5 "spec" says "rs.rows[n]", but WebKit only impelments "rs.rows.item(n)". We do both (and property iterator).
-We add a "forwardOnly" property that stops Qt caching results (code promises to only go forward
-through the data.
-*/
-
-
-/*!
- \qmlmodule QtQuick.LocalStorage 2.\QtMinorVersion
- \title Qt Quick Local Storage QML Types
- \ingroup qmlmodules
- \brief Provides a JavaScript object singleton type for accessing a local
- SQLite database
-
- This is a singleton type for reading and writing to SQLite databases.
-
-
- \section1 Methods
-
- \list
- \li object \b{\l{#openDatabaseSync}{openDatabaseSync}}(string name, string version, string description, int estimated_size, jsobject callback(db))
- \endlist
-
-
- \section1 Detailed Description
-
- To use the types in this module, import the module and call the
- relevant functions using the \c LocalStorage type:
-
- \qml \QtMinorVersion
- import QtQuick 2.\1
- import QtQuick.LocalStorage 2.\1
-
- Item {
- Component.onCompleted: {
- var db = LocalStorage.openDatabaseSync(...)
- }
- }
- \endqml
-
-
-These databases are user-specific and QML-specific, but accessible to all QML applications.
-They are stored in the \c Databases subdirectory
-of QQmlEngine::offlineStoragePath(), currently as SQLite databases.
-
-Database connections are automatically closed during Javascript garbage collection.
-
-The API can be used from JavaScript functions in your QML:
-
-\snippet qml/localstorage/hello.qml 0
-
-The API conforms to the Synchronous API of the HTML5 Web Database API,
-\link http://www.w3.org/TR/2009/WD-webdatabase-20091029/ W3C Working Draft 29 October 2009\endlink.
-
-The \l{Qt Quick Examples - Local Storage}{SQL Local Storage example} demonstrates the basics of
-using the Offline Storage API.
-
-\section3 Open or Create a Database
-
-\qml \QtMinorVersion
-import QtQuick.LocalStorage 2.\1 as Sql
-
-db = Sql.openDatabaseSync(identifier, version, description, estimated_size, callback(db))
-\endqml
-
-The above code returns the database identified by \e identifier. If the database does not already exist, it
-is created, and the function \e callback is called with the database as a parameter. \e identifier is the
-name of the physical file (with or without full path) containing the database. \e description and
-\e estimated_size are written to the INI file (described below), but are currently unused.
-
-May throw exception with code property SQLException.DATABASE_ERR, or SQLException.VERSION_ERR.
-
-When a database is first created, an INI file is also created specifying its characteristics:
-
-\table
-\header \li \b {Key} \li \b {Value}
-\row \li Identifier \li The name of the database passed to \c openDatabase()
-\row \li Version \li The version of the database passed to \c openDatabase()
-\row \li Description \li The description of the database passed to \c openDatabase()
-\row \li EstimatedSize \li The estimated size (in bytes) of the database passed to \c openDatabase()
-\row \li Driver \li Currently "QSQLITE"
-\endtable
-
-This data can be used by application tools.
-
-\section3 db.changeVersion(from, to, callback(tx))
-
-This method allows you to perform a \e{Scheme Upgrade}. If it succeeds it returns a new
-database object of version \e to. Otherwise it returns \e undefined.
-
-If the current version of \e db is not \e from, then an exception is thrown.
-
-Otherwise, a database transaction is created and passed to \e callback. In this function,
-you can call \e executeSql on \e tx to upgrade the database.
-
-May throw exception with code property SQLException.DATABASE_ERR or SQLException.UNKNOWN_ERR.
-
-See example below.
-
-\badcode
- var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000);
- if (db.version == "0.1") {
- db.changeVersion("0.1", "0.2", function(tx) {
- tx.executeSql("INSERT INTO trip_log VALUES(?, ?, ?)",
- [ "01/10/2016","Sylling - Vikersund", "53" ]);
- }
- });
-\endcode
-
-\section3 db.transaction(callback(tx))
-
-This method creates a read/write transaction and passed to \e callback. In this function,
-you can call \e executeSql on \e tx to read and modify the database.
-
-If the callback throws exceptions, the transaction is rolled back.
-Below you will find an example of a database transaction which catches exceptions.
-
-
-\quotefromfile localstorage/localstorage/Database.js
-\skipuntil dbInit()
-\printto dbGetHandle
-
-In the example you can see an \c insert statement where values are assigned to the fields,
-and the record is written into the table. That is an \c insert statement with a syntax that is usual
-for a relational database. It is however also possible to work with JSON objects and
-store them in a table.
-
-Let's suppose a simple example where we store trips in JSON format using \c date as the unique key.
-An example of a table that could be used for that purpose:
-
-\badcode
- create table trip_log(date text, data text)
-\endcode
-
-The assignment of values to a JSON object:
-
-\badcode
- var obj = {description = "Vikersund - Noresund", distance = "60"}
-\endcode
-
-In that case, the data could be saved in the following way:
-
-\badcode
- db.transaction(function(tx) {
- result = tx.executeSQL("insert into trip_log values (?,?)",
- ["01/11/2016", JSON.stringify(obj)])
-
-\endcode
-
-\section3 db.readTransaction(callback(tx))
-
-This method creates a read-only transaction and passed to \e callback. In this function,
-you can call \e executeSql on \e tx to read the database (with \c select statements).
-
-\section3 results = tx.executeSql(statement, values)
-
-This method executes an SQL \e statement, binding the list of \e values to SQL positional parameters ("?").
-
-It returns a results object, with the following properties:
-
-\table
-\header \li \b {Type} \li \b {Property} \li \b {Value} \li \b {Applicability}
-\row \li int \li rows.length \li The number of rows in the result \li SELECT
-\row \li var \li rows.item(i) \li Function that returns row \e i of the result \li SELECT
-\row \li int \li rowsAffected \li The number of rows affected by a modification \li UPDATE, DELETE
-\row \li string \li insertId \li The id of the row inserted \li INSERT
-\endtable
-
-May throw exception with code property SQLException.DATABASE_ERR, SQLException.SYNTAX_ERR, or SQLException.UNKNOWN_ERR.
-
-See below for an example:
-
-\quotefromfile localstorage/localstorage/Database.js
-\skipto dbReadAll()
-\printto dbUpdate(Pdate
-
-\section1 Method Documentation
-
-\target openDatabaseSync
-\code
-object openDatabaseSync(string name, string version, string description, int estimated_size, jsobject callback(db))
-\endcode
-
-Opens or creates a local storage sql database by the given parameters.
-
-\list
-\li \c name is the database name
-\li \c version is the database version
-\li \c description is the database display name
-\li \c estimated_size is the database's estimated size, in bytes
-\li \c callback is an optional parameter, which is invoked if the database has not yet been created.
-\endlist
-
-Returns the created database object.
-
-*/
-class QQuickLocalStorage : public QObject
-{
- Q_OBJECT
-public:
- QQuickLocalStorage(QObject *parent=nullptr) : QObject(parent)
- {
- }
- ~QQuickLocalStorage() override {
- }
-
- Q_INVOKABLE void openDatabaseSync(QQmlV4Function* args);
-};
-
-void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
-{
-#if QT_CONFIG(settings)
- QV4::Scope scope(args->v4engine());
- if (scope.engine->qmlEngine()->offlineStoragePath().isEmpty())
- V4THROW_SQL2(SQLEXCEPTION_DATABASE_ERR, QQmlEngine::tr("SQL: can't create database, offline storage is disabled."));
-
- QV4::ScopedValue v(scope);
- QString dbname = (v = (*args)[0])->toQStringNoThrow();
- QString dbversion = (v = (*args)[1])->toQStringNoThrow();
- QString dbdescription = (v = (*args)[2])->toQStringNoThrow();
- int dbestimatedsize = (v = (*args)[3])->toInt32();
- FunctionObject *dbcreationCallback = (v = (*args)[4])->as<FunctionObject>();
- QString basename = args->v4engine()->qmlEngine()->offlineStorageDatabaseFilePath(dbname);
- QFileInfo dbFile(basename);
- if (!QDir().mkpath(dbFile.dir().absolutePath())) {
- const QString message = QQmlEngine::tr("LocalStorage: can't create path %1").
- arg(QDir::toNativeSeparators(dbFile.dir().absolutePath()));
- V4THROW_SQL2(SQLEXCEPTION_DATABASE_ERR, message);
- }
- QString dbid = dbFile.fileName();
- bool created = false;
- QString version = dbversion;
- QSqlDatabase database;
-
- {
- QSettings ini(basename+QLatin1String(".ini"),QSettings::IniFormat);
-
- if (QSqlDatabase::connectionNames().contains(dbid)) {
- database = QSqlDatabase::database(dbid);
- version = ini.value(QLatin1String("Version")).toString();
- if (version != dbversion && !dbversion.isEmpty() && !version.isEmpty())
- V4THROW_SQL2(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("SQL: database version mismatch"));
- } else {
- created = !QFile::exists(basename+QLatin1String(".sqlite"));
- if (created) {
- ini.setValue(QLatin1String("Name"), dbname);
- if (dbcreationCallback)
- version = QString();
- ini.setValue(QLatin1String("Version"), version);
- ini.setValue(QLatin1String("Description"), dbdescription);
- ini.setValue(QLatin1String("EstimatedSize"), dbestimatedsize);
- ini.setValue(QLatin1String("Driver"), QLatin1String("QSQLITE"));
- } else {
- if (!dbversion.isEmpty() && ini.value(QLatin1String("Version")) != dbversion) {
- // Incompatible
- V4THROW_SQL2(SQLEXCEPTION_VERSION_ERR,QQmlEngine::tr("SQL: database version mismatch"));
- }
- version = ini.value(QLatin1String("Version")).toString();
- }
- database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
- database.setDatabaseName(basename+QLatin1String(".sqlite"));
- }
- if (!database.isOpen())
- database.open();
- }
-
- QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
- QV4::ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value());
- db->setPrototypeUnchecked(p.getPointer());
- *db->d()->database = database;
- *db->d()->version = version;
-
- if (created && dbcreationCallback) {
- JSCallData jsCall(scope, 1);
- *jsCall->thisObject = scope.engine->globalObject;
- jsCall->args[0] = db;
- dbcreationCallback->call(jsCall);
- }
-
- args->setReturnValue(db.asReturnedValue());
-#else
- Q_UNUSED(args)
-#endif // settings
-}
-
-static QObject *module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine)
-{
- Q_UNUSED(engine)
- Q_UNUSED(scriptEngine)
- QQuickLocalStorage *api = new QQuickLocalStorage();
-
- return api;
-}
-
class QQmlLocalStoragePlugin : public QQmlExtensionPlugin
{
Q_OBJECT
@@ -823,7 +56,7 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.LocalStorage"));
- qmlRegisterSingletonType<QQuickLocalStorage>(uri, 2, 0, "LocalStorage", module_api_factory);
+ qmlRegisterTypesAndRevisions<QQuickLocalStorage>(uri, 2);
qmlRegisterModule(uri, 2, 15);
}
diff --git a/src/imports/localstorage/qquicklocalstorage.cpp b/src/imports/localstorage/qquicklocalstorage.cpp
new file mode 100644
index 0000000000..333e697e3c
--- /dev/null
+++ b/src/imports/localstorage/qquicklocalstorage.cpp
@@ -0,0 +1,792 @@
+/****************************************************************************
+**
+** 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: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 "qquicklocalstorage_p.h"
+
+#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qv4global_p.h>
+#include <QtQml/private/qv4scopedvalue_p.h>
+#include <QtQml/private/qv4object_p.h>
+#include <QtQml/private/qv4sqlerrors_p.h>
+#include <QtQml/private/qv4jscall_p.h>
+#include <QtQml/private/qv4objectiterator_p.h>
+
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdir.h>
+
+#include <QtSql/qsqldatabase.h>
+#include <QtSql/qsqlquery.h>
+#include <QtSql/qsqlrecord.h>
+#include <QtSql/qsqlerror.h>
+
+#if QT_CONFIG(settings)
+#include <QtCore/qsettings.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define V4THROW_SQL(error, desc) { \
+ QV4::ScopedString v(scope, scope.engine->newString(desc)); \
+ QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
+ ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Value::fromInt32(error))); \
+ scope.engine->throwError(ex); \
+ RETURN_UNDEFINED(); \
+}
+
+#define V4THROW_SQL2(error, desc) { \
+ QV4::ScopedString v(scope, scope.engine->newString(desc)); \
+ QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
+ ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Value::fromInt32(error))); \
+ args->setReturnValue(scope.engine->throwError(ex)); \
+ return; \
+}
+
+#define V4THROW_REFERENCE(string) { \
+ QV4::ScopedString v(scope, scope.engine->newString(string)); \
+ scope.engine->throwReferenceError(v); \
+ RETURN_UNDEFINED(); \
+}
+
+
+class QQmlSqlDatabaseData : public QV4::ExecutionEngine::Deletable
+{
+public:
+ QQmlSqlDatabaseData(QV4::ExecutionEngine *engine);
+ ~QQmlSqlDatabaseData() override;
+
+ QV4::PersistentValue databaseProto;
+ QV4::PersistentValue queryProto;
+ QV4::PersistentValue rowsProto;
+};
+
+V4_DEFINE_EXTENSION(QQmlSqlDatabaseData, databaseData)
+
+namespace QV4 {
+
+namespace Heap {
+ struct QQmlSqlDatabaseWrapper : public Object {
+ enum Type { Database, Query, Rows };
+ void init()
+ {
+ Object::init();
+ type = Database;
+ database = new QSqlDatabase;
+ version = new QString;
+ sqlQuery = new QSqlQuery;
+ }
+
+ void destroy() {
+ delete database;
+ delete version;
+ delete sqlQuery;
+ Object::destroy();
+ }
+
+ Type type;
+ QSqlDatabase *database;
+
+ QString *version; // type == Database
+
+ bool inTransaction; // type == Query
+ bool readonly; // type == Query
+
+ QSqlQuery *sqlQuery; // type == Rows
+ bool forwardOnly; // type == Rows
+ };
+}
+
+class QQmlSqlDatabaseWrapper : public Object
+{
+public:
+ V4_OBJECT2(QQmlSqlDatabaseWrapper, Object)
+ V4_NEEDS_DESTROY
+
+ static Heap::QQmlSqlDatabaseWrapper *create(QV4::ExecutionEngine *engine)
+ {
+ return engine->memoryManager->allocate<QQmlSqlDatabaseWrapper>();
+ }
+
+ ~QQmlSqlDatabaseWrapper() {
+ }
+
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+};
+
+}
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
+
+
+
+static ReturnedValue qmlsqldatabase_version(const FunctionObject *b, const Value *thisObject, const QV4::Value *, int)
+{
+ Scope scope(b);
+ QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
+ V4THROW_REFERENCE("Not a SQLDatabase object");
+
+ RETURN_RESULT(Encode(scope.engine->newString(*r->d()->version)));
+}
+
+static ReturnedValue qmlsqldatabase_rows_length(const FunctionObject *b, const Value *thisObject, const QV4::Value *, int)
+{
+ Scope scope(b);
+ QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
+ V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ int s = r->d()->sqlQuery->size();
+ if (s < 0) {
+ // Inefficient
+ if (r->d()->sqlQuery->last()) {
+ s = r->d()->sqlQuery->at() + 1;
+ } else {
+ s = 0;
+ }
+ }
+ RETURN_RESULT(Encode(s));
+}
+
+static ReturnedValue qmlsqldatabase_rows_forwardOnly(const FunctionObject *b, const Value *thisObject, const QV4::Value *, int)
+{
+ Scope scope(b);
+ QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
+ V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
+ RETURN_RESULT(Encode(r->d()->sqlQuery->isForwardOnly()));
+}
+
+static ReturnedValue qmlsqldatabase_rows_setForwardOnly(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
+ V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
+ if (argc < 1)
+ RETURN_RESULT(scope.engine->throwTypeError());
+
+ r->d()->sqlQuery->setForwardOnly(argv[0].toBoolean());
+ RETURN_UNDEFINED();
+}
+
+QQmlSqlDatabaseData::~QQmlSqlDatabaseData()
+{
+}
+
+static ReturnedValue qmlsqldatabase_rows_index(const QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = nullptr)
+{
+ Scope scope(v4);
+
+ if (r->d()->sqlQuery->at() == (int)index || r->d()->sqlQuery->seek(index)) {
+ QSqlRecord record = r->d()->sqlQuery->record();
+ // XXX optimize
+ ScopedObject row(scope, v4->newObject());
+ for (int ii = 0; ii < record.count(); ++ii) {
+ QVariant v = record.value(ii);
+ ScopedString s(scope, v4->newIdentifier(record.fieldName(ii)));
+ ScopedValue val(scope, v.isNull() ? Encode::null() : v4->fromVariant(v));
+ row->put(s.getPointer(), val);
+ }
+ if (hasProperty)
+ *hasProperty = true;
+ return row.asReturnedValue();
+ } else {
+ if (hasProperty)
+ *hasProperty = false;
+ return Encode::undefined();
+ }
+}
+
+ReturnedValue QQmlSqlDatabaseWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
+{
+ if (!id.isArrayIndex())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
+ uint index = id.asArrayIndex();
+ Q_ASSERT(m->as<QQmlSqlDatabaseWrapper>());
+ const QQmlSqlDatabaseWrapper *r = static_cast<const QQmlSqlDatabaseWrapper *>(m);
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
+ return qmlsqldatabase_rows_index(r, r->engine(), index, hasProperty);
+}
+
+static ReturnedValue qmlsqldatabase_rows_item(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
+ V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ RETURN_RESULT(qmlsqldatabase_rows_index(r, scope.engine, argc ? argv[0].toUInt32() : 0));
+}
+
+static QVariant toSqlVariant(QV4::ExecutionEngine *engine, const QV4::ScopedValue &value)
+{
+ // toVariant() maps a null JS value to QVariant(VoidStar), but the SQL module
+ // expects a null variant. (this is because of QTBUG-40880)
+ if (value->isNull())
+ return QVariant();
+ return engine->toVariant(value, /*typehint*/-1);
+}
+
+static ReturnedValue qmlsqldatabase_executeSql(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Query)
+ V4THROW_REFERENCE("Not a SQLDatabase::Query object");
+
+ if (!r->d()->inTransaction)
+ V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,QQmlEngine::tr("executeSql called outside transaction()"));
+
+ QSqlDatabase db = *r->d()->database;
+
+ QString sql = argc ? argv[0].toQString() : QString();
+
+ if (r->d()->readonly && !sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) {
+ V4THROW_SQL(SQLEXCEPTION_SYNTAX_ERR, QQmlEngine::tr("Read-only Transaction"));
+ }
+
+ QSqlQuery query(db);
+ bool err = false;
+
+ ScopedValue result(scope, Value::undefinedValue());
+
+ if (query.prepare(sql)) {
+ if (argc > 1) {
+ ScopedValue values(scope, argv[1]);
+ if (values->as<ArrayObject>()) {
+ ScopedArrayObject array(scope, values);
+ quint32 size = array->getLength();
+ QV4::ScopedValue v(scope);
+ for (quint32 ii = 0; ii < size; ++ii) {
+ query.bindValue(ii, toSqlVariant(scope.engine, (v = array->get(ii))));
+ }
+ } else if (values->as<Object>()) {
+ ScopedObject object(scope, values);
+ ObjectIterator it(scope, object, ObjectIterator::EnumerableOnly);
+ ScopedValue key(scope);
+ QV4::ScopedValue val(scope);
+ while (1) {
+ key = it.nextPropertyName(val);
+ if (key->isNull())
+ break;
+ QVariant v = toSqlVariant(scope.engine, val);
+ if (key->isString()) {
+ query.bindValue(key->stringValue()->toQString(), v);
+ } else {
+ Q_ASSERT(key->isInteger());
+ query.bindValue(key->integerValue(), v);
+ }
+ }
+ } else {
+ query.bindValue(0, toSqlVariant(scope.engine, values));
+ }
+ }
+ if (query.exec()) {
+ QV4::Scoped<QQmlSqlDatabaseWrapper> rows(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ QV4::ScopedObject p(scope, databaseData(scope.engine)->rowsProto.value());
+ rows->setPrototypeUnchecked(p.getPointer());
+ rows->d()->type = Heap::QQmlSqlDatabaseWrapper::Rows;
+ *rows->d()->database = db;
+ *rows->d()->sqlQuery = query;
+
+ ScopedObject resultObject(scope, scope.engine->newObject());
+ result = resultObject.asReturnedValue();
+ // XXX optimize
+ ScopedString s(scope);
+ ScopedValue v(scope);
+ resultObject->put((s = scope.engine->newIdentifier("rowsAffected")).getPointer(), (v = Value::fromInt32(query.numRowsAffected())));
+ resultObject->put((s = scope.engine->newIdentifier("insertId")).getPointer(), (v = scope.engine->newString(query.lastInsertId().toString())));
+ resultObject->put((s = scope.engine->newIdentifier("rows")).getPointer(), rows);
+ } else {
+ err = true;
+ }
+ } else {
+ err = true;
+ }
+ if (err)
+ V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,query.lastError().text());
+
+ RETURN_RESULT(result->asReturnedValue());
+}
+
+struct TransactionRollback {
+ QSqlDatabase *db;
+ bool *inTransactionFlag;
+
+ TransactionRollback(QSqlDatabase *database, bool *transactionFlag)
+ : db(database)
+ , inTransactionFlag(transactionFlag)
+ {
+ if (inTransactionFlag)
+ *inTransactionFlag = true;
+ }
+
+ ~TransactionRollback()
+ {
+ if (inTransactionFlag)
+ *inTransactionFlag = false;
+ if (db)
+ db->rollback();
+ }
+
+ void clear() {
+ db = nullptr;
+ if (inTransactionFlag)
+ *inTransactionFlag = false;
+ inTransactionFlag = nullptr;
+ }
+};
+
+
+static ReturnedValue qmlsqldatabase_changeVersion(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ if (argc < 2)
+ RETURN_UNDEFINED();
+
+ Scoped<QQmlSqlDatabaseWrapper> r(scope, *thisObject);
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
+ V4THROW_REFERENCE("Not a SQLDatabase object");
+
+ QSqlDatabase db = *r->d()->database;
+ QString from_version = argv[0].toQString();
+ QString to_version = argv[1].toQString();
+ ScopedFunctionObject callback(scope, argc > 2 ? argv[2] : Value::undefinedValue());
+
+ if (from_version != *r->d()->version)
+ V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(*r->d()->version));
+
+ bool ok = true;
+ if (!!callback) {
+ Scoped<QQmlSqlDatabaseWrapper> query(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
+ query->setPrototypeUnchecked(p.getPointer());
+ query->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
+ *query->d()->database = db;
+ *query->d()->version = *r->d()->version;
+
+ ok = false;
+ db.transaction();
+
+ JSCallData jsCall(scope, 1);
+ *jsCall->thisObject = scope.engine->globalObject;
+ jsCall->args[0] = query;
+
+ TransactionRollback rollbackOnException(&db, &query->d()->inTransaction);
+ callback->call(jsCall);
+ rollbackOnException.clear();
+ if (!db.commit()) {
+ db.rollback();
+ V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR,QQmlEngine::tr("SQL transaction failed"));
+ } else {
+ ok = true;
+ }
+ }
+
+ if (ok) {
+ Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value());
+ w->setPrototypeUnchecked(p.getPointer());
+ w->d()->type = Heap::QQmlSqlDatabaseWrapper::Database;
+ *w->d()->database = db;
+ *w->d()->version = to_version;
+#if QT_CONFIG(settings)
+ const QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(scope.engine->qmlEngine());
+ QSettings ini(enginePrivate->offlineStorageDatabaseDirectory() + db.connectionName() + QLatin1String(".ini"), QSettings::IniFormat);
+ ini.setValue(QLatin1String("Version"), to_version);
+#endif
+ RETURN_RESULT(w.asReturnedValue());
+ }
+
+ RETURN_UNDEFINED();
+}
+
+static ReturnedValue qmlsqldatabase_transaction_shared(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc, bool readOnly)
+{
+ Scope scope(b);
+ QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, thisObject->as<QQmlSqlDatabaseWrapper>());
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
+ V4THROW_REFERENCE("Not a SQLDatabase object");
+
+ const FunctionObject *callback = argc ? argv[0].as<FunctionObject>() : nullptr;
+ if (!callback)
+ V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback"));
+
+ QSqlDatabase db = *r->d()->database;
+
+ Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ QV4::ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
+ w->setPrototypeUnchecked(p.getPointer());
+ w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
+ *w->d()->database = db;
+ *w->d()->version = *r->d()->version;
+ w->d()->readonly = readOnly;
+
+ db.transaction();
+ if (callback) {
+ JSCallData jsCall(scope, 1);
+ *jsCall->thisObject = scope.engine->globalObject;
+ jsCall->args[0] = w;
+ TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
+ callback->call(jsCall);
+ rollbackOnException.clear();
+
+ if (!db.commit())
+ db.rollback();
+ }
+
+ RETURN_UNDEFINED();
+}
+
+static ReturnedValue qmlsqldatabase_transaction(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ return qmlsqldatabase_transaction_shared(f, thisObject, argv, argc, false);
+}
+
+static ReturnedValue qmlsqldatabase_read_transaction(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ return qmlsqldatabase_transaction_shared(f, thisObject, argv, argc, true);
+}
+
+QQmlSqlDatabaseData::QQmlSqlDatabaseData(ExecutionEngine *v4)
+{
+ Scope scope(v4);
+ {
+ ScopedObject proto(scope, v4->newObject());
+ proto->defineDefaultProperty(QStringLiteral("transaction"), qmlsqldatabase_transaction);
+ proto->defineDefaultProperty(QStringLiteral("readTransaction"), qmlsqldatabase_read_transaction);
+ proto->defineAccessorProperty(QStringLiteral("version"), qmlsqldatabase_version, nullptr);
+ proto->defineDefaultProperty(QStringLiteral("changeVersion"), qmlsqldatabase_changeVersion);
+ databaseProto = proto;
+ }
+
+ {
+ ScopedObject proto(scope, v4->newObject());
+ proto->defineDefaultProperty(QStringLiteral("executeSql"), qmlsqldatabase_executeSql);
+ queryProto = proto;
+ }
+ {
+ ScopedObject proto(scope, v4->newObject());
+ proto->defineDefaultProperty(QStringLiteral("item"), qmlsqldatabase_rows_item);
+ proto->defineAccessorProperty(QStringLiteral("length"), qmlsqldatabase_rows_length, nullptr);
+ proto->defineAccessorProperty(QStringLiteral("forwardOnly"),
+ qmlsqldatabase_rows_forwardOnly, qmlsqldatabase_rows_setForwardOnly);
+ rowsProto = proto;
+ }
+}
+
+/*
+HTML5 "spec" says "rs.rows[n]", but WebKit only impelments "rs.rows.item(n)". We do both (and property iterator).
+We add a "forwardOnly" property that stops Qt caching results (code promises to only go forward
+through the data.
+*/
+
+
+/*!
+ \qmlmodule QtQuick.LocalStorage 2.\QtMinorVersion
+ \title Qt Quick Local Storage QML Types
+ \ingroup qmlmodules
+ \brief Provides a JavaScript object singleton type for accessing a local
+ SQLite database
+
+ This is a singleton type for reading and writing to SQLite databases.
+
+
+ \section1 Methods
+
+ \list
+ \li object \b{\l{#openDatabaseSync}{openDatabaseSync}}(string name, string version, string description, int estimated_size, jsobject callback(db))
+ \endlist
+
+
+ \section1 Detailed Description
+
+ To use the types in this module, import the module and call the
+ relevant functions using the \c LocalStorage type:
+
+ \qml \QtMinorVersion
+ import QtQuick 2.\1
+ import QtQuick.LocalStorage 2.\1
+
+ Item {
+ Component.onCompleted: {
+ var db = LocalStorage.openDatabaseSync(...)
+ }
+ }
+ \endqml
+
+
+These databases are user-specific and QML-specific, but accessible to all QML applications.
+They are stored in the \c Databases subdirectory
+of QQmlEngine::offlineStoragePath(), currently as SQLite databases.
+
+Database connections are automatically closed during Javascript garbage collection.
+
+The API can be used from JavaScript functions in your QML:
+
+\snippet qml/localstorage/hello.qml 0
+
+The API conforms to the Synchronous API of the HTML5 Web Database API,
+\link http://www.w3.org/TR/2009/WD-webdatabase-20091029/ W3C Working Draft 29 October 2009\endlink.
+
+The \l{Qt Quick Examples - Local Storage}{SQL Local Storage example} demonstrates the basics of
+using the Offline Storage API.
+
+\section3 Open or Create a Database
+
+\qml \QtMinorVersion
+import QtQuick.LocalStorage 2.\1 as Sql
+
+db = Sql.openDatabaseSync(identifier, version, description, estimated_size, callback(db))
+\endqml
+
+The above code returns the database identified by \e identifier. If the database does not already exist, it
+is created, and the function \e callback is called with the database as a parameter. \e identifier is the
+name of the physical file (with or without full path) containing the database. \e description and
+\e estimated_size are written to the INI file (described below), but are currently unused.
+
+May throw exception with code property SQLException.DATABASE_ERR, or SQLException.VERSION_ERR.
+
+When a database is first created, an INI file is also created specifying its characteristics:
+
+\table
+\header \li \b {Key} \li \b {Value}
+\row \li Identifier \li The name of the database passed to \c openDatabase()
+\row \li Version \li The version of the database passed to \c openDatabase()
+\row \li Description \li The description of the database passed to \c openDatabase()
+\row \li EstimatedSize \li The estimated size (in bytes) of the database passed to \c openDatabase()
+\row \li Driver \li Currently "QSQLITE"
+\endtable
+
+This data can be used by application tools.
+
+\section3 db.changeVersion(from, to, callback(tx))
+
+This method allows you to perform a \e{Scheme Upgrade}. If it succeeds it returns a new
+database object of version \e to. Otherwise it returns \e undefined.
+
+If the current version of \e db is not \e from, then an exception is thrown.
+
+Otherwise, a database transaction is created and passed to \e callback. In this function,
+you can call \e executeSql on \e tx to upgrade the database.
+
+May throw exception with code property SQLException.DATABASE_ERR or SQLException.UNKNOWN_ERR.
+
+See example below.
+
+\badcode
+ var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000);
+ if (db.version == "0.1") {
+ db.changeVersion("0.1", "0.2", function(tx) {
+ tx.executeSql("INSERT INTO trip_log VALUES(?, ?, ?)",
+ [ "01/10/2016","Sylling - Vikersund", "53" ]);
+ }
+ });
+\endcode
+
+\section3 db.transaction(callback(tx))
+
+This method creates a read/write transaction and passed to \e callback. In this function,
+you can call \e executeSql on \e tx to read and modify the database.
+
+If the callback throws exceptions, the transaction is rolled back.
+Below you will find an example of a database transaction which catches exceptions.
+
+
+\quotefromfile localstorage/localstorage/Database.js
+\skipuntil dbInit()
+\printto dbGetHandle
+
+In the example you can see an \c insert statement where values are assigned to the fields,
+and the record is written into the table. That is an \c insert statement with a syntax that is usual
+for a relational database. It is however also possible to work with JSON objects and
+store them in a table.
+
+Let's suppose a simple example where we store trips in JSON format using \c date as the unique key.
+An example of a table that could be used for that purpose:
+
+\badcode
+ create table trip_log(date text, data text)
+\endcode
+
+The assignment of values to a JSON object:
+
+\badcode
+ var obj = {description = "Vikersund - Noresund", distance = "60"}
+\endcode
+
+In that case, the data could be saved in the following way:
+
+\badcode
+ db.transaction(function(tx) {
+ result = tx.executeSQL("insert into trip_log values (?,?)",
+ ["01/11/2016", JSON.stringify(obj)])
+
+\endcode
+
+\section3 db.readTransaction(callback(tx))
+
+This method creates a read-only transaction and passed to \e callback. In this function,
+you can call \e executeSql on \e tx to read the database (with \c select statements).
+
+\section3 results = tx.executeSql(statement, values)
+
+This method executes an SQL \e statement, binding the list of \e values to SQL positional parameters ("?").
+
+It returns a results object, with the following properties:
+
+\table
+\header \li \b {Type} \li \b {Property} \li \b {Value} \li \b {Applicability}
+\row \li int \li rows.length \li The number of rows in the result \li SELECT
+\row \li var \li rows.item(i) \li Function that returns row \e i of the result \li SELECT
+\row \li int \li rowsAffected \li The number of rows affected by a modification \li UPDATE, DELETE
+\row \li string \li insertId \li The id of the row inserted \li INSERT
+\endtable
+
+May throw exception with code property SQLException.DATABASE_ERR, SQLException.SYNTAX_ERR, or SQLException.UNKNOWN_ERR.
+
+See below for an example:
+
+\quotefromfile localstorage/localstorage/Database.js
+\skipto dbReadAll()
+\printto dbUpdate(Pdate
+
+\section1 Method Documentation
+
+\target openDatabaseSync
+\code
+object openDatabaseSync(string name, string version, string description, int estimated_size, jsobject callback(db))
+\endcode
+
+Opens or creates a local storage sql database by the given parameters.
+
+\list
+\li \c name is the database name
+\li \c version is the database version
+\li \c description is the database display name
+\li \c estimated_size is the database's estimated size, in bytes
+\li \c callback is an optional parameter, which is invoked if the database has not yet been created.
+\endlist
+
+Returns the created database object.
+
+*/
+
+void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
+{
+#if QT_CONFIG(settings)
+ QV4::Scope scope(args->v4engine());
+ if (scope.engine->qmlEngine()->offlineStoragePath().isEmpty())
+ V4THROW_SQL2(SQLEXCEPTION_DATABASE_ERR, QQmlEngine::tr("SQL: can't create database, offline storage is disabled."));
+
+ QV4::ScopedValue v(scope);
+ QString dbname = (v = (*args)[0])->toQStringNoThrow();
+ QString dbversion = (v = (*args)[1])->toQStringNoThrow();
+ QString dbdescription = (v = (*args)[2])->toQStringNoThrow();
+ int dbestimatedsize = (v = (*args)[3])->toInt32();
+ FunctionObject *dbcreationCallback = (v = (*args)[4])->as<FunctionObject>();
+ QString basename = args->v4engine()->qmlEngine()->offlineStorageDatabaseFilePath(dbname);
+ QFileInfo dbFile(basename);
+ if (!QDir().mkpath(dbFile.dir().absolutePath())) {
+ const QString message = QQmlEngine::tr("LocalStorage: can't create path %1").
+ arg(QDir::toNativeSeparators(dbFile.dir().absolutePath()));
+ V4THROW_SQL2(SQLEXCEPTION_DATABASE_ERR, message);
+ }
+ QString dbid = dbFile.fileName();
+ bool created = false;
+ QString version = dbversion;
+ QSqlDatabase database;
+
+ {
+ QSettings ini(basename+QLatin1String(".ini"),QSettings::IniFormat);
+
+ if (QSqlDatabase::connectionNames().contains(dbid)) {
+ database = QSqlDatabase::database(dbid);
+ version = ini.value(QLatin1String("Version")).toString();
+ if (version != dbversion && !dbversion.isEmpty() && !version.isEmpty())
+ V4THROW_SQL2(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("SQL: database version mismatch"));
+ } else {
+ created = !QFile::exists(basename+QLatin1String(".sqlite"));
+ if (created) {
+ ini.setValue(QLatin1String("Name"), dbname);
+ if (dbcreationCallback)
+ version = QString();
+ ini.setValue(QLatin1String("Version"), version);
+ ini.setValue(QLatin1String("Description"), dbdescription);
+ ini.setValue(QLatin1String("EstimatedSize"), dbestimatedsize);
+ ini.setValue(QLatin1String("Driver"), QLatin1String("QSQLITE"));
+ } else {
+ if (!dbversion.isEmpty() && ini.value(QLatin1String("Version")) != dbversion) {
+ // Incompatible
+ V4THROW_SQL2(SQLEXCEPTION_VERSION_ERR,QQmlEngine::tr("SQL: database version mismatch"));
+ }
+ version = ini.value(QLatin1String("Version")).toString();
+ }
+ database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
+ database.setDatabaseName(basename+QLatin1String(".sqlite"));
+ }
+ if (!database.isOpen())
+ database.open();
+ }
+
+ QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ QV4::ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value());
+ db->setPrototypeUnchecked(p.getPointer());
+ *db->d()->database = database;
+ *db->d()->version = version;
+
+ if (created && dbcreationCallback) {
+ JSCallData jsCall(scope, 1);
+ *jsCall->thisObject = scope.engine->globalObject;
+ jsCall->args[0] = db;
+ dbcreationCallback->call(jsCall);
+ }
+
+ args->setReturnValue(db.asReturnedValue());
+#else
+ Q_UNUSED(args)
+#endif // settings
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/localstorage/qquicklocalstorage_p.h b/src/imports/localstorage/qquicklocalstorage_p.h
new file mode 100644
index 0000000000..d2ebc85ce9
--- /dev/null
+++ b/src/imports/localstorage/qquicklocalstorage_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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: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 QQUICKLOCALSTORAGE_P_H
+#define QQUICKLOCALSTORAGE_P_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 <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+#include <QtQml/private/qv4engine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickLocalStorage : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(LocalStorage)
+ QML_SINGLETON
+
+public:
+ QQuickLocalStorage(QObject *parent = nullptr) : QObject(parent) {}
+ ~QQuickLocalStorage() override = default;
+
+ Q_INVOKABLE void openDatabaseSync(QQmlV4Function* args);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKLOCALSTORAGE_P_H
diff --git a/src/imports/models/plugins.qmltypes b/src/imports/models/plugins.qmltypes
index 0d8b94df23..89a839e502 100644
--- a/src/imports/models/plugins.qmltypes
+++ b/src/imports/models/plugins.qmltypes
@@ -398,7 +398,7 @@ Module {
defaultProperty: "delegate"
prototype: "QQmlInstanceModel"
exports: ["QtQml.Models/DelegateModel 2.1"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [1]
attachedType: "QQmlDelegateModelAttached"
Property { name: "model"; type: "QVariant" }
Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
@@ -434,7 +434,7 @@ Module {
name: "QQmlDelegateModelGroup"
prototype: "QObject"
exports: ["QtQml.Models/DelegateModelGroup 2.1"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [1]
Property { name: "count"; type: "int"; isReadonly: true }
Property { name: "name"; type: "string" }
Property { name: "includeByDefault"; type: "bool" }
@@ -484,16 +484,68 @@ Module {
}
Component { name: "QQmlDelegateModelParts"; prototype: "QObject" }
Component {
+ name: "QQmlInstanceModel"
+ prototype: "QObject"
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Signal {
+ name: "modelUpdated"
+ Parameter { name: "changeSet"; type: "QQmlChangeSet" }
+ Parameter { name: "reset"; type: "bool" }
+ }
+ Signal {
+ name: "createdItem"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "initItem"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "destroyingItem"
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ }
+ Component {
+ name: "QQmlInstantiator"
+ defaultProperty: "delegate"
+ prototype: "QObject"
+ exports: ["QtQml.Models/Instantiator 2.14"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "active"; type: "bool" }
+ Property { name: "asynchronous"; type: "bool" }
+ Property { name: "model"; type: "QVariant" }
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
+ Property { name: "object"; type: "QObject"; isReadonly: true; isPointer: true }
+ Signal {
+ name: "objectAdded"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "objectRemoved"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "objectAt"
+ type: "QObject*"
+ Parameter { name: "index"; type: "int" }
+ }
+ }
+ Component {
name: "QQmlListElement"
prototype: "QObject"
exports: ["QtQml.Models/ListElement 2.1"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [1]
}
Component {
name: "QQmlListModel"
prototype: "QAbstractListModel"
- exports: ["QtQml.Models/ListModel 2.1"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQml.Models/ListModel 2.1", "QtQml.Models/ListModel 2.14"]
+ exportMetaObjectRevisions: [1, 14]
Property { name: "count"; type: "int"; isReadonly: true }
Property { name: "dynamicRoles"; type: "bool" }
Property { name: "agent"; revision: 14; type: "QObject"; isReadonly: true; isPointer: true }
@@ -590,7 +642,7 @@ Module {
"QtQml.Models/ObjectModel 2.1",
"QtQml.Models/ObjectModel 2.3"
]
- exportMetaObjectRevisions: [0, 3]
+ exportMetaObjectRevisions: [1, 3]
attachedType: "QQmlObjectModelAttached"
Property { name: "children"; type: "QObject"; isList: true; isReadonly: true }
Method { name: "clear"; revision: 3 }
@@ -646,7 +698,7 @@ Module {
defaultProperty: "data"
prototype: "QObject"
exports: ["QtQml.Models/Package 2.14"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [14]
attachedType: "QQuickPackageAttached"
Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
}
diff --git a/src/imports/particles/plugins.qmltypes b/src/imports/particles/plugins.qmltypes
index 0fe5dc808c..48da0b26ed 100644
--- a/src/imports/particles/plugins.qmltypes
+++ b/src/imports/particles/plugins.qmltypes
@@ -12,8 +12,14 @@ Module {
name: "QQuickAgeAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/Age 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Age 2.0",
+ "QtQuick.Particles/Age 2.1",
+ "QtQuick.Particles/Age 2.11",
+ "QtQuick.Particles/Age 2.4",
+ "QtQuick.Particles/Age 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "lifeLeft"; type: "int" }
Property { name: "advancePosition"; type: "bool" }
Signal {
@@ -79,8 +85,14 @@ Module {
name: "QQuickAttractorAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/Attractor 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Attractor 2.0",
+ "QtQuick.Particles/Attractor 2.1",
+ "QtQuick.Particles/Attractor 2.11",
+ "QtQuick.Particles/Attractor 2.4",
+ "QtQuick.Particles/Attractor 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "Proportion"
values: {
@@ -157,8 +169,14 @@ Module {
name: "QQuickCustomAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/Affector 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Affector 2.0",
+ "QtQuick.Particles/Affector 2.1",
+ "QtQuick.Particles/Affector 2.11",
+ "QtQuick.Particles/Affector 2.4",
+ "QtQuick.Particles/Affector 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "relative"; type: "bool" }
Property { name: "position"; type: "QQuickDirection"; isPointer: true }
Property { name: "velocity"; type: "QQuickDirection"; isPointer: true }
@@ -205,8 +223,14 @@ Module {
name: "QQuickCustomParticle"
defaultProperty: "data"
prototype: "QQuickParticlePainter"
- exports: ["QtQuick.Particles/CustomParticle 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/CustomParticle 2.0",
+ "QtQuick.Particles/CustomParticle 2.1",
+ "QtQuick.Particles/CustomParticle 2.11",
+ "QtQuick.Particles/CustomParticle 2.4",
+ "QtQuick.Particles/CustomParticle 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "fragmentShader"; type: "QByteArray" }
Property { name: "vertexShader"; type: "QByteArray" }
}
@@ -236,8 +260,14 @@ Module {
name: "QQuickFrictionAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/Friction 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Friction 2.0",
+ "QtQuick.Particles/Friction 2.1",
+ "QtQuick.Particles/Friction 2.11",
+ "QtQuick.Particles/Friction 2.4",
+ "QtQuick.Particles/Friction 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "factor"; type: "double" }
Property { name: "threshold"; type: "double" }
Signal {
@@ -261,8 +291,14 @@ Module {
name: "QQuickGravityAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/Gravity 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Gravity 2.0",
+ "QtQuick.Particles/Gravity 2.1",
+ "QtQuick.Particles/Gravity 2.11",
+ "QtQuick.Particles/Gravity 2.4",
+ "QtQuick.Particles/Gravity 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "magnitude"; type: "double" }
Property { name: "acceleration"; type: "double" }
Property { name: "angle"; type: "double" }
@@ -291,8 +327,14 @@ Module {
name: "QQuickGroupGoalAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/GroupGoal 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/GroupGoal 2.0",
+ "QtQuick.Particles/GroupGoal 2.1",
+ "QtQuick.Particles/GroupGoal 2.11",
+ "QtQuick.Particles/GroupGoal 2.4",
+ "QtQuick.Particles/GroupGoal 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "goalState"; type: "string" }
Property { name: "jump"; type: "bool" }
Signal {
@@ -316,8 +358,14 @@ Module {
name: "QQuickImageParticle"
defaultProperty: "data"
prototype: "QQuickParticlePainter"
- exports: ["QtQuick.Particles/ImageParticle 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/ImageParticle 2.0",
+ "QtQuick.Particles/ImageParticle 2.1",
+ "QtQuick.Particles/ImageParticle 2.11",
+ "QtQuick.Particles/ImageParticle 2.4",
+ "QtQuick.Particles/ImageParticle 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "Status"
values: {
@@ -495,8 +543,14 @@ Module {
name: "QQuickItemParticle"
defaultProperty: "data"
prototype: "QQuickParticlePainter"
- exports: ["QtQuick.Particles/ItemParticle 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/ItemParticle 2.0",
+ "QtQuick.Particles/ItemParticle 2.1",
+ "QtQuick.Particles/ItemParticle 2.11",
+ "QtQuick.Particles/ItemParticle 2.4",
+ "QtQuick.Particles/ItemParticle 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
attachedType: "QQuickItemParticleAttached"
Property { name: "fade"; type: "bool" }
Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
@@ -575,9 +629,15 @@ Module {
name: "QQuickParticleAffector"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick.Particles/ParticleAffector 2.0"]
+ exports: [
+ "QtQuick.Particles/ParticleAffector 2.0",
+ "QtQuick.Particles/ParticleAffector 2.1",
+ "QtQuick.Particles/ParticleAffector 2.11",
+ "QtQuick.Particles/ParticleAffector 2.4",
+ "QtQuick.Particles/ParticleAffector 2.7"
+ ]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "system"; type: "QQuickParticleSystem"; isPointer: true }
Property { name: "groups"; type: "QStringList" }
Property { name: "whenCollidingWith"; type: "QStringList" }
@@ -643,8 +703,14 @@ Module {
name: "QQuickParticleEmitter"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick.Particles/Emitter 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Emitter 2.0",
+ "QtQuick.Particles/Emitter 2.1",
+ "QtQuick.Particles/Emitter 2.11",
+ "QtQuick.Particles/Emitter 2.4",
+ "QtQuick.Particles/Emitter 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "Lifetime"
values: {
@@ -839,9 +905,15 @@ Module {
name: "QQuickParticlePainter"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick.Particles/ParticlePainter 2.0"]
+ exports: [
+ "QtQuick.Particles/ParticlePainter 2.0",
+ "QtQuick.Particles/ParticlePainter 2.1",
+ "QtQuick.Particles/ParticlePainter 2.11",
+ "QtQuick.Particles/ParticlePainter 2.4",
+ "QtQuick.Particles/ParticlePainter 2.7"
+ ]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "system"; type: "QQuickParticleSystem"; isPointer: true }
Property { name: "groups"; type: "QStringList" }
Signal { name: "countChanged" }
@@ -871,8 +943,14 @@ Module {
name: "QQuickParticleSystem"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick.Particles/ParticleSystem 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/ParticleSystem 2.0",
+ "QtQuick.Particles/ParticleSystem 2.1",
+ "QtQuick.Particles/ParticleSystem 2.11",
+ "QtQuick.Particles/ParticleSystem 2.4",
+ "QtQuick.Particles/ParticleSystem 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "running"; type: "bool" }
Property { name: "paused"; type: "bool" }
Property { name: "empty"; type: "bool"; isReadonly: true }
@@ -966,8 +1044,14 @@ Module {
name: "QQuickSpriteGoalAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/SpriteGoal 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/SpriteGoal 2.0",
+ "QtQuick.Particles/SpriteGoal 2.1",
+ "QtQuick.Particles/SpriteGoal 2.11",
+ "QtQuick.Particles/SpriteGoal 2.4",
+ "QtQuick.Particles/SpriteGoal 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "goalState"; type: "string" }
Property { name: "jump"; type: "bool" }
Property { name: "systemStates"; type: "bool" }
@@ -997,6 +1081,56 @@ Module {
}
}
Component {
+ name: "QQuickStochasticState"
+ prototype: "QObject"
+ Property { name: "duration"; type: "int" }
+ Property { name: "durationVariation"; type: "int" }
+ Property { name: "randomStart"; type: "bool" }
+ Property { name: "to"; type: "QVariantMap" }
+ Property { name: "name"; type: "string" }
+ Signal {
+ name: "durationChanged"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Signal {
+ name: "nameChanged"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Signal {
+ name: "toChanged"
+ Parameter { name: "arg"; type: "QVariantMap" }
+ }
+ Signal {
+ name: "durationVariationChanged"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Signal { name: "entered" }
+ Signal {
+ name: "randomStartChanged"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setDuration"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setName"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setTo"
+ Parameter { name: "arg"; type: "QVariantMap" }
+ }
+ Method {
+ name: "setDurationVariation"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setRandomStart"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ }
+ Component {
name: "QQuickTargetDirection"
prototype: "QQuickDirection"
exports: ["QtQuick.Particles/TargetDirection 2.0"]
@@ -1069,8 +1203,14 @@ Module {
name: "QQuickTrailEmitter"
defaultProperty: "data"
prototype: "QQuickParticleEmitter"
- exports: ["QtQuick.Particles/TrailEmitter 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/TrailEmitter 2.0",
+ "QtQuick.Particles/TrailEmitter 2.1",
+ "QtQuick.Particles/TrailEmitter 2.11",
+ "QtQuick.Particles/TrailEmitter 2.4",
+ "QtQuick.Particles/TrailEmitter 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "EmitSize"
values: {
@@ -1132,8 +1272,14 @@ Module {
name: "QQuickTurbulenceAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/Turbulence 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Turbulence 2.0",
+ "QtQuick.Particles/Turbulence 2.1",
+ "QtQuick.Particles/Turbulence 2.11",
+ "QtQuick.Particles/Turbulence 2.4",
+ "QtQuick.Particles/Turbulence 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "strength"; type: "double" }
Property { name: "noiseSource"; type: "QUrl" }
Signal {
@@ -1157,8 +1303,14 @@ Module {
name: "QQuickWanderAffector"
defaultProperty: "data"
prototype: "QQuickParticleAffector"
- exports: ["QtQuick.Particles/Wander 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Particles/Wander 2.0",
+ "QtQuick.Particles/Wander 2.1",
+ "QtQuick.Particles/Wander 2.11",
+ "QtQuick.Particles/Wander 2.4",
+ "QtQuick.Particles/Wander 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "AffectableParameters"
values: {
diff --git a/src/imports/qtqml/plugins.qmltypes b/src/imports/qtqml/plugins.qmltypes
index 63f5bada9b..e4ddb3ddd1 100644
--- a/src/imports/qtqml/plugins.qmltypes
+++ b/src/imports/qtqml/plugins.qmltypes
@@ -10,8 +10,8 @@ Module {
dependencies: []
Component {
name: "QObject"
- exports: ["QML/QtObject 1.0", "QtQml/QtObject 2.0"]
- exportMetaObjectRevisions: [0, 0]
+ exports: ["QtQml/QtObject 2.0"]
+ exportMetaObjectRevisions: [0]
Property { name: "objectName"; type: "string" }
Signal {
name: "objectNameChanged"
@@ -52,8 +52,8 @@ Module {
Component {
name: "QQmlComponent"
prototype: "QObject"
- exports: ["QML/Component 1.0", "QtQml/Component 2.0"]
- exportMetaObjectRevisions: [0, 0]
+ exports: ["QtQml/Component 2.0"]
+ exportMetaObjectRevisions: [0]
attachedType: "QQmlComponentAttached"
Enum {
name: "CompilationMode"
@@ -170,7 +170,7 @@ Module {
name: "QQmlLocale"
exports: ["QtQml/Locale 2.2"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [2]
Enum {
name: "MeasurementSystem"
values: {
@@ -213,7 +213,7 @@ Module {
name: "QQmlLoggingCategory"
prototype: "QObject"
exports: ["QtQml/LoggingCategory 2.12", "QtQml/LoggingCategory 2.8"]
- exportMetaObjectRevisions: [12, 0]
+ exportMetaObjectRevisions: [12, 8]
Enum {
name: "DefaultLogLevel"
values: {
@@ -242,18 +242,4 @@ Module {
Method { name: "stop" }
Method { name: "restart" }
}
- Component {
- name: "QQuickMouseEvent"
- prototype: "QObject"
- Property { name: "x"; type: "double"; isReadonly: true }
- Property { name: "y"; type: "double"; isReadonly: true }
- Property { name: "button"; type: "int"; isReadonly: true }
- Property { name: "buttons"; type: "int"; isReadonly: true }
- Property { name: "modifiers"; type: "int"; isReadonly: true }
- Property { name: "source"; revision: 7; type: "int"; isReadonly: true }
- Property { name: "wasHeld"; type: "bool"; isReadonly: true }
- Property { name: "isClick"; type: "bool"; isReadonly: true }
- Property { name: "accepted"; type: "bool" }
- Property { name: "flags"; revision: 11; type: "int"; isReadonly: true }
- }
}
diff --git a/src/imports/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes
index c8aae2087d..a773a8c428 100644
--- a/src/imports/qtquick2/plugins.qmltypes
+++ b/src/imports/qtquick2/plugins.qmltypes
@@ -449,6 +449,22 @@ Module {
}
}
Component {
+ name: "QObject"
+ exports: ["QtQuick/QtObject 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "objectName"; type: "string" }
+ Signal {
+ name: "objectNameChanged"
+ Parameter { name: "objectName"; type: "string" }
+ }
+ Method { name: "toString" }
+ Method { name: "destroy" }
+ Method {
+ name: "destroy"
+ Parameter { name: "delay"; type: "int" }
+ }
+ }
+ Component {
name: "QPointingDeviceUniqueId"
exports: ["QtQuick/PointingDeviceUniqueId 2.9"]
isCreatable: false
@@ -482,6 +498,92 @@ Module {
}
}
Component {
+ name: "QQmlBind"
+ prototype: "QObject"
+ exports: ["QtQuick/Binding 2.0", "QtQuick/Binding 2.8"]
+ exportMetaObjectRevisions: [0, 8]
+ Enum {
+ name: "RestorationMode"
+ values: {
+ "RestoreNone": 0,
+ "RestoreBinding": 1,
+ "RestoreValue": 2,
+ "RestoreBindingOrValue": 3
+ }
+ }
+ Property { name: "target"; type: "QObject"; isPointer: true }
+ Property { name: "property"; type: "string" }
+ Property { name: "value"; type: "QVariant" }
+ Property { name: "when"; type: "bool" }
+ Property { name: "delayed"; revision: 8; type: "bool" }
+ Property { name: "restoreMode"; revision: 14; type: "RestorationMode" }
+ }
+ Component {
+ name: "QQmlComponent"
+ prototype: "QObject"
+ exports: ["QtQuick/Component 2.0"]
+ exportMetaObjectRevisions: [0]
+ attachedType: "QQmlComponentAttached"
+ Enum {
+ name: "CompilationMode"
+ values: {
+ "PreferSynchronous": 0,
+ "Asynchronous": 1
+ }
+ }
+ Enum {
+ name: "Status"
+ values: {
+ "Null": 0,
+ "Ready": 1,
+ "Loading": 2,
+ "Error": 3
+ }
+ }
+ Property { name: "progress"; type: "double"; isReadonly: true }
+ Property { name: "status"; type: "Status"; isReadonly: true }
+ Property { name: "url"; type: "QUrl"; isReadonly: true }
+ Signal {
+ name: "statusChanged"
+ Parameter { type: "QQmlComponent::Status" }
+ }
+ Signal {
+ name: "progressChanged"
+ Parameter { type: "double" }
+ }
+ Method {
+ name: "loadUrl"
+ Parameter { name: "url"; type: "QUrl" }
+ }
+ Method {
+ name: "loadUrl"
+ Parameter { name: "url"; type: "QUrl" }
+ Parameter { name: "mode"; type: "CompilationMode" }
+ }
+ Method {
+ name: "setData"
+ Parameter { type: "QByteArray" }
+ Parameter { name: "baseUrl"; type: "QUrl" }
+ }
+ Method { name: "errorString"; type: "string" }
+ }
+ Component {
+ name: "QQmlComponentAttached"
+ prototype: "QObject"
+ Signal { name: "completed" }
+ Signal { name: "destruction" }
+ }
+ Component {
+ name: "QQmlConnections"
+ prototype: "QObject"
+ exports: ["QtQuick/Connections 2.0", "QtQuick/Connections 2.7"]
+ exportMetaObjectRevisions: [0, 3]
+ Property { name: "target"; type: "QObject"; isPointer: true }
+ Property { name: "enabled"; revision: 3; type: "bool" }
+ Property { name: "ignoreUnknownSignals"; type: "bool" }
+ Signal { name: "enabledChanged"; revision: 3 }
+ }
+ Component {
name: "QQmlDelegateModel"
defaultProperty: "delegate"
prototype: "QQmlInstanceModel"
@@ -634,6 +736,58 @@ Module {
Property { name: "bezierCurve"; type: "QVariantList" }
}
Component {
+ name: "QQmlInstanceModel"
+ prototype: "QObject"
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Signal {
+ name: "modelUpdated"
+ Parameter { name: "changeSet"; type: "QQmlChangeSet" }
+ Parameter { name: "reset"; type: "bool" }
+ }
+ Signal {
+ name: "createdItem"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "initItem"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "destroyingItem"
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ }
+ Component {
+ name: "QQmlInstantiator"
+ defaultProperty: "delegate"
+ prototype: "QObject"
+ exports: ["QtQuick/Instantiator 2.1"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "active"; type: "bool" }
+ Property { name: "asynchronous"; type: "bool" }
+ Property { name: "model"; type: "QVariant" }
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
+ Property { name: "object"; type: "QObject"; isReadonly: true; isPointer: true }
+ Signal {
+ name: "objectAdded"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "objectRemoved"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "objectAt"
+ type: "QObject*"
+ Parameter { name: "index"; type: "int" }
+ }
+ }
+ Component {
name: "QQmlListElement"
prototype: "QObject"
exports: ["QtQuick/ListElement 2.0"]
@@ -733,6 +887,70 @@ Module {
Method { name: "sync" }
}
Component {
+ name: "QQmlLocale"
+ exports: ["QtQuick/Locale 2.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "MeasurementSystem"
+ values: {
+ "MetricSystem": 0,
+ "ImperialSystem": 1,
+ "ImperialUSSystem": 1,
+ "ImperialUKSystem": 2
+ }
+ }
+ Enum {
+ name: "FormatType"
+ values: {
+ "LongFormat": 0,
+ "ShortFormat": 1,
+ "NarrowFormat": 2
+ }
+ }
+ Enum {
+ name: "CurrencySymbolFormat"
+ values: {
+ "CurrencyIsoCode": 0,
+ "CurrencySymbol": 1,
+ "CurrencyDisplayName": 2
+ }
+ }
+ Enum {
+ name: "DayOfWeek"
+ values: {
+ "Sunday": 0,
+ "Monday": 1,
+ "Tuesday": 2,
+ "Wednesday": 3,
+ "Thursday": 4,
+ "Friday": 5,
+ "Saturday": 6
+ }
+ }
+ }
+ Component {
+ name: "QQmlLoggingCategory"
+ prototype: "QObject"
+ exports: [
+ "QtQuick/LoggingCategory 2.12",
+ "QtQuick/LoggingCategory 2.8"
+ ]
+ exportMetaObjectRevisions: [12, 0]
+ Enum {
+ name: "DefaultLogLevel"
+ values: {
+ "Debug": 0,
+ "Info": 4,
+ "Warning": 1,
+ "Critical": 2,
+ "Fatal": 3
+ }
+ }
+ Property { name: "name"; type: "string" }
+ Property { name: "defaultLogLevel"; revision: 12; type: "DefaultLogLevel" }
+ }
+ Component {
name: "QQmlObjectModel"
defaultProperty: "children"
prototype: "QQmlInstanceModel"
@@ -789,6 +1007,21 @@ Module {
Property { name: "index"; type: "int"; isReadonly: true }
}
Component {
+ name: "QQmlTimer"
+ prototype: "QObject"
+ exports: ["QtQuick/Timer 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "interval"; type: "int" }
+ Property { name: "running"; type: "bool" }
+ Property { name: "repeat"; type: "bool" }
+ Property { name: "triggeredOnStart"; type: "bool" }
+ Property { name: "parent"; type: "QObject"; isReadonly: true; isPointer: true }
+ Signal { name: "triggered" }
+ Method { name: "start" }
+ Method { name: "stop" }
+ Method { name: "restart" }
+ }
+ Component {
name: "QQuickAbstractAnimation"
prototype: "QObject"
exports: ["QtQuick/Animation 2.0", "QtQuick/Animation 2.12"]
@@ -935,8 +1168,11 @@ Module {
Component {
name: "QQuickAnchorAnimation"
prototype: "QQuickAbstractAnimation"
- exports: ["QtQuick/AnchorAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/AnchorAnimation 2.0",
+ "QtQuick/AnchorAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "targets"; type: "QQuickItem"; isList: true; isReadonly: true }
Property { name: "duration"; type: "int" }
Property { name: "easing"; type: "QEasingCurve" }
@@ -1010,8 +1246,16 @@ Module {
name: "QQuickAnimatedImage"
defaultProperty: "data"
prototype: "QQuickImage"
- exports: ["QtQuick/AnimatedImage 2.0", "QtQuick/AnimatedImage 2.11"]
- exportMetaObjectRevisions: [0, 11]
+ exports: [
+ "QtQuick/AnimatedImage 2.0",
+ "QtQuick/AnimatedImage 2.1",
+ "QtQuick/AnimatedImage 2.11",
+ "QtQuick/AnimatedImage 2.3",
+ "QtQuick/AnimatedImage 2.4",
+ "QtQuick/AnimatedImage 2.5",
+ "QtQuick/AnimatedImage 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 3, 4, 5, 7]
Property { name: "playing"; type: "bool" }
Property { name: "paused"; type: "bool" }
Property { name: "currentFrame"; type: "int" }
@@ -1025,8 +1269,15 @@ Module {
name: "QQuickAnimatedSprite"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/AnimatedSprite 2.0", "QtQuick/AnimatedSprite 2.12"]
- exportMetaObjectRevisions: [0, 12]
+ exports: [
+ "QtQuick/AnimatedSprite 2.0",
+ "QtQuick/AnimatedSprite 2.1",
+ "QtQuick/AnimatedSprite 2.11",
+ "QtQuick/AnimatedSprite 2.12",
+ "QtQuick/AnimatedSprite 2.4",
+ "QtQuick/AnimatedSprite 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 12, 4, 7]
Enum {
name: "LoopParameters"
values: {
@@ -1203,9 +1454,9 @@ Module {
Component {
name: "QQuickAnimator"
prototype: "QQuickAbstractAnimation"
- exports: ["QtQuick/Animator 2.2"]
+ exports: ["QtQuick/Animator 2.12", "QtQuick/Animator 2.2"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12, 2]
Property { name: "target"; type: "QQuickItem"; isPointer: true }
Property { name: "easing"; type: "QEasingCurve" }
Property { name: "duration"; type: "int" }
@@ -1256,11 +1507,15 @@ Module {
prototype: "QQuickImplicitSizeItem"
exports: [
"QtQuick/Positioner 2.0",
+ "QtQuick/Positioner 2.1",
+ "QtQuick/Positioner 2.11",
+ "QtQuick/Positioner 2.4",
"QtQuick/Positioner 2.6",
+ "QtQuick/Positioner 2.7",
"QtQuick/Positioner 2.9"
]
isCreatable: false
- exportMetaObjectRevisions: [0, 6, 9]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 6, 7, 9]
attachedType: "QQuickPositionerAttached"
Property { name: "spacing"; type: "double" }
Property { name: "populate"; type: "QQuickTransition"; isPointer: true }
@@ -1293,8 +1548,14 @@ Module {
name: "QQuickBorderImage"
defaultProperty: "data"
prototype: "QQuickImageBase"
- exports: ["QtQuick/BorderImage 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/BorderImage 2.0",
+ "QtQuick/BorderImage 2.1",
+ "QtQuick/BorderImage 2.11",
+ "QtQuick/BorderImage 2.4",
+ "QtQuick/BorderImage 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "TileMode"
values: {
@@ -1312,7 +1573,7 @@ Module {
name: "QQuickBorderImageMesh"
prototype: "QQuickShaderEffectMesh"
exports: ["QtQuick/BorderImageMesh 2.8"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [8]
Enum {
name: "TileMode"
values: {
@@ -1330,8 +1591,14 @@ Module {
name: "QQuickCanvasItem"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/Canvas 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/Canvas 2.0",
+ "QtQuick/Canvas 2.1",
+ "QtQuick/Canvas 2.11",
+ "QtQuick/Canvas 2.4",
+ "QtQuick/Canvas 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "RenderTarget"
values: {
@@ -1422,8 +1689,8 @@ Module {
Component {
name: "QQuickColorAnimation"
prototype: "QQuickPropertyAnimation"
- exports: ["QtQuick/ColorAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/ColorAnimation 2.0", "QtQuick/ColorAnimation 2.12"]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "from"; type: "QColor" }
Property { name: "to"; type: "QColor" }
}
@@ -1431,8 +1698,16 @@ Module {
name: "QQuickColumn"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Column 2.0", "QtQuick/Column 2.6"]
- exportMetaObjectRevisions: [0, 6]
+ exports: [
+ "QtQuick/Column 2.0",
+ "QtQuick/Column 2.1",
+ "QtQuick/Column 2.11",
+ "QtQuick/Column 2.4",
+ "QtQuick/Column 2.6",
+ "QtQuick/Column 2.7",
+ "QtQuick/Column 2.9"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 6, 7, 9]
}
Component {
name: "QQuickCurve"
@@ -1519,7 +1794,7 @@ Module {
prototype: "QObject"
exports: ["QtQuick/DragAxis 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Property { name: "minimum"; type: "double" }
Property { name: "maximum"; type: "double" }
Property { name: "enabled"; type: "bool" }
@@ -1527,8 +1802,8 @@ Module {
Component {
name: "QQuickDragHandler"
prototype: "QQuickMultiPointHandler"
- exports: ["QtQuick/DragHandler 2.12"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/DragHandler 2.12", "QtQuick/DragHandler 2.14"]
+ exportMetaObjectRevisions: [12, 14]
Enum {
name: "SnapMode"
values: {
@@ -1541,14 +1816,21 @@ Module {
Property { name: "xAxis"; type: "QQuickDragAxis"; isReadonly: true; isPointer: true }
Property { name: "yAxis"; type: "QQuickDragAxis"; isReadonly: true; isPointer: true }
Property { name: "translation"; type: "QVector2D"; isReadonly: true }
- Property { name: "snapMode"; type: "SnapMode" }
+ Property { name: "snapMode"; revision: 14; type: "SnapMode" }
+ Signal { name: "snapModeChanged"; revision: 14 }
}
Component {
name: "QQuickDropArea"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/DropArea 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/DropArea 2.0",
+ "QtQuick/DropArea 2.1",
+ "QtQuick/DropArea 2.11",
+ "QtQuick/DropArea 2.4",
+ "QtQuick/DropArea 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "containsDrag"; type: "bool"; isReadonly: true }
Property { name: "keys"; type: "QStringList" }
Property { name: "drag"; type: "QQuickDropAreaDrag"; isReadonly: true; isPointer: true }
@@ -1625,7 +1907,7 @@ Module {
prototype: "QObject"
exports: ["QtQuick/EventPoint 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Enum {
name: "States"
values: {
@@ -1664,7 +1946,7 @@ Module {
prototype: "QQuickEventPoint"
exports: ["QtQuick/EventTouchPoint 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Property { name: "rotation"; type: "double"; isReadonly: true }
Property { name: "pressure"; type: "double"; isReadonly: true }
Property { name: "ellipseDiameters"; type: "QSizeF"; isReadonly: true }
@@ -1676,11 +1958,15 @@ Module {
prototype: "QQuickItem"
exports: [
"QtQuick/Flickable 2.0",
+ "QtQuick/Flickable 2.1",
"QtQuick/Flickable 2.10",
+ "QtQuick/Flickable 2.11",
"QtQuick/Flickable 2.12",
+ "QtQuick/Flickable 2.4",
+ "QtQuick/Flickable 2.7",
"QtQuick/Flickable 2.9"
]
- exportMetaObjectRevisions: [0, 10, 12, 9]
+ exportMetaObjectRevisions: [0, 1, 10, 11, 12, 4, 7, 9]
Enum {
name: "BoundsBehavior"
values: {
@@ -1805,8 +2091,14 @@ Module {
name: "QQuickFlipable"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/Flipable 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/Flipable 2.0",
+ "QtQuick/Flipable 2.1",
+ "QtQuick/Flipable 2.11",
+ "QtQuick/Flipable 2.4",
+ "QtQuick/Flipable 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "Side"
values: {
@@ -1822,8 +2114,16 @@ Module {
name: "QQuickFlow"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Flow 2.0", "QtQuick/Flow 2.6"]
- exportMetaObjectRevisions: [0, 6]
+ exports: [
+ "QtQuick/Flow 2.0",
+ "QtQuick/Flow 2.1",
+ "QtQuick/Flow 2.11",
+ "QtQuick/Flow 2.4",
+ "QtQuick/Flow 2.6",
+ "QtQuick/Flow 2.7",
+ "QtQuick/Flow 2.9"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 6, 7, 9]
Enum {
name: "Flow"
values: {
@@ -1839,8 +2139,14 @@ Module {
name: "QQuickFocusScope"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/FocusScope 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/FocusScope 2.0",
+ "QtQuick/FocusScope 2.1",
+ "QtQuick/FocusScope 2.11",
+ "QtQuick/FocusScope 2.4",
+ "QtQuick/FocusScope 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
}
Component {
name: "QQuickFontLoader"
@@ -1864,7 +2170,7 @@ Module {
name: "QQuickFontMetrics"
prototype: "QObject"
exports: ["QtQuick/FontMetrics 2.4"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [4]
Property { name: "font"; type: "QFont" }
Property { name: "ascent"; type: "double"; isReadonly: true }
Property { name: "descent"; type: "double"; isReadonly: true }
@@ -2011,7 +2317,7 @@ Module {
prototype: "QObject"
exports: ["QtQuick/GraphicsInfo 2.8"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [8]
Enum {
name: "GraphicsApi"
values: {
@@ -2080,8 +2386,16 @@ Module {
name: "QQuickGrid"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Grid 2.0", "QtQuick/Grid 2.1", "QtQuick/Grid 2.6"]
- exportMetaObjectRevisions: [0, 1, 6]
+ exports: [
+ "QtQuick/Grid 2.0",
+ "QtQuick/Grid 2.1",
+ "QtQuick/Grid 2.11",
+ "QtQuick/Grid 2.4",
+ "QtQuick/Grid 2.6",
+ "QtQuick/Grid 2.7",
+ "QtQuick/Grid 2.9"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 6, 7, 9]
Enum {
name: "Flow"
values: {
@@ -2150,10 +2464,16 @@ Module {
exports: [
"QtQuick/GridView 2.0",
"QtQuick/GridView 2.1",
+ "QtQuick/GridView 2.10",
+ "QtQuick/GridView 2.11",
+ "QtQuick/GridView 2.12",
"QtQuick/GridView 2.13",
- "QtQuick/GridView 2.7"
+ "QtQuick/GridView 2.3",
+ "QtQuick/GridView 2.4",
+ "QtQuick/GridView 2.7",
+ "QtQuick/GridView 2.9"
]
- exportMetaObjectRevisions: [0, 1, 13, 7]
+ exportMetaObjectRevisions: [0, 1, 10, 11, 12, 13, 3, 4, 7, 9]
attachedType: "QQuickGridViewAttached"
Enum {
name: "Flow"
@@ -2185,7 +2505,7 @@ Module {
name: "QQuickHoverHandler"
prototype: "QQuickSinglePointHandler"
exports: ["QtQuick/HoverHandler 2.12"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Property { name: "hovered"; type: "bool"; isReadonly: true }
}
Component {
@@ -2194,10 +2514,15 @@ Module {
prototype: "QQuickImageBase"
exports: [
"QtQuick/Image 2.0",
+ "QtQuick/Image 2.1",
+ "QtQuick/Image 2.11",
+ "QtQuick/Image 2.14",
"QtQuick/Image 2.3",
- "QtQuick/Image 2.5"
+ "QtQuick/Image 2.4",
+ "QtQuick/Image 2.5",
+ "QtQuick/Image 2.7"
]
- exportMetaObjectRevisions: [0, 3, 5]
+ exportMetaObjectRevisions: [0, 1, 11, 14, 3, 4, 5, 7]
Enum {
name: "HAlignment"
values: {
@@ -2253,6 +2578,9 @@ Module {
name: "QQuickImageBase"
defaultProperty: "data"
prototype: "QQuickImplicitSizeItem"
+ exports: ["QtQuick/ImageBase 2.14"]
+ isCreatable: false
+ exportMetaObjectRevisions: [14]
Enum {
name: "Status"
values: {
@@ -2269,6 +2597,8 @@ Module {
Property { name: "cache"; type: "bool" }
Property { name: "sourceSize"; type: "QSize" }
Property { name: "mirror"; type: "bool" }
+ Property { name: "currentFrame"; revision: 14; type: "int" }
+ Property { name: "frameCount"; revision: 14; type: "int"; isReadonly: true }
Signal {
name: "sourceChanged"
Parameter { type: "QUrl" }
@@ -2281,6 +2611,8 @@ Module {
name: "progressChanged"
Parameter { name: "progress"; type: "double" }
}
+ Signal { name: "currentFrameChanged"; revision: 14 }
+ Signal { name: "frameCountChanged"; revision: 14 }
}
Component {
name: "QQuickImplicitSizeItem"
@@ -2563,12 +2895,17 @@ Module {
prototype: "QQuickFlickable"
exports: [
"QtQuick/ItemView 2.1",
+ "QtQuick/ItemView 2.10",
+ "QtQuick/ItemView 2.11",
+ "QtQuick/ItemView 2.12",
"QtQuick/ItemView 2.13",
"QtQuick/ItemView 2.3",
- "QtQuick/ItemView 2.7"
+ "QtQuick/ItemView 2.4",
+ "QtQuick/ItemView 2.7",
+ "QtQuick/ItemView 2.9"
]
isCreatable: false
- exportMetaObjectRevisions: [1, 13, 3, 7]
+ exportMetaObjectRevisions: [1, 10, 11, 12, 13, 3, 4, 7, 9]
Enum {
name: "LayoutDirection"
values: {
@@ -2921,10 +3258,16 @@ Module {
exports: [
"QtQuick/ListView 2.0",
"QtQuick/ListView 2.1",
+ "QtQuick/ListView 2.10",
+ "QtQuick/ListView 2.11",
+ "QtQuick/ListView 2.12",
+ "QtQuick/ListView 2.13",
+ "QtQuick/ListView 2.3",
"QtQuick/ListView 2.4",
- "QtQuick/ListView 2.7"
+ "QtQuick/ListView 2.7",
+ "QtQuick/ListView 2.9"
]
- exportMetaObjectRevisions: [0, 1, 4, 7]
+ exportMetaObjectRevisions: [0, 1, 10, 11, 12, 13, 3, 4, 7, 9]
attachedType: "QQuickListViewAttached"
Enum {
name: "Orientation"
@@ -2977,8 +3320,14 @@ Module {
name: "QQuickLoader"
defaultProperty: "data"
prototype: "QQuickImplicitSizeItem"
- exports: ["QtQuick/Loader 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/Loader 2.0",
+ "QtQuick/Loader 2.1",
+ "QtQuick/Loader 2.11",
+ "QtQuick/Loader 2.4",
+ "QtQuick/Loader 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "Status"
values: {
@@ -3005,7 +3354,7 @@ Module {
name: "QQuickMatrix4x4"
prototype: "QQuickTransform"
exports: ["QtQuick/Matrix4x4 2.3"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [3]
Property { name: "matrix"; type: "QMatrix4x4" }
}
Component {
@@ -3014,11 +3363,14 @@ Module {
prototype: "QQuickItem"
exports: [
"QtQuick/MouseArea 2.0",
+ "QtQuick/MouseArea 2.1",
+ "QtQuick/MouseArea 2.11",
"QtQuick/MouseArea 2.4",
"QtQuick/MouseArea 2.5",
+ "QtQuick/MouseArea 2.7",
"QtQuick/MouseArea 2.9"
]
- exportMetaObjectRevisions: [0, 4, 5, 9]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 5, 7, 9]
Property { name: "mouseX"; type: "double"; isReadonly: true }
Property { name: "mouseY"; type: "double"; isReadonly: true }
Property { name: "containsMouse"; type: "bool"; isReadonly: true }
@@ -3079,6 +3431,20 @@ Module {
Signal { name: "pressAndHoldIntervalChanged"; revision: 9 }
}
Component {
+ name: "QQuickMouseEvent"
+ prototype: "QObject"
+ Property { name: "x"; type: "double"; isReadonly: true }
+ Property { name: "y"; type: "double"; isReadonly: true }
+ Property { name: "button"; type: "int"; isReadonly: true }
+ Property { name: "buttons"; type: "int"; isReadonly: true }
+ Property { name: "modifiers"; type: "int"; isReadonly: true }
+ Property { name: "source"; revision: 7; type: "int"; isReadonly: true }
+ Property { name: "wasHeld"; type: "bool"; isReadonly: true }
+ Property { name: "isClick"; type: "bool"; isReadonly: true }
+ Property { name: "accepted"; type: "bool" }
+ Property { name: "flags"; revision: 11; type: "int"; isReadonly: true }
+ }
+ Component {
name: "QQuickMultiPointHandler"
prototype: "QQuickPointerDeviceHandler"
Property { name: "minimumPointCount"; type: "int" }
@@ -3090,8 +3456,14 @@ Module {
name: "QQuickMultiPointTouchArea"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/MultiPointTouchArea 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/MultiPointTouchArea 2.0",
+ "QtQuick/MultiPointTouchArea 2.1",
+ "QtQuick/MultiPointTouchArea 2.11",
+ "QtQuick/MultiPointTouchArea 2.4",
+ "QtQuick/MultiPointTouchArea 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "touchPoints"; type: "QQuickTouchPoint"; isList: true; isReadonly: true }
Property { name: "minimumTouchPoints"; type: "int" }
Property { name: "maximumTouchPoints"; type: "int" }
@@ -3124,23 +3496,29 @@ Module {
Component {
name: "QQuickNumberAnimation"
prototype: "QQuickPropertyAnimation"
- exports: ["QtQuick/NumberAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/NumberAnimation 2.0",
+ "QtQuick/NumberAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "from"; type: "double" }
Property { name: "to"; type: "double" }
}
Component {
name: "QQuickOpacityAnimator"
prototype: "QQuickAnimator"
- exports: ["QtQuick/OpacityAnimator 2.2"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/OpacityAnimator 2.12",
+ "QtQuick/OpacityAnimator 2.2"
+ ]
+ exportMetaObjectRevisions: [12, 2]
}
Component {
name: "QQuickOpenGLInfo"
prototype: "QObject"
exports: ["QtQuick/OpenGLInfo 2.4"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [4]
Enum {
name: "ContextProfile"
values: {
@@ -3180,9 +3558,15 @@ Module {
name: "QQuickPaintedItem"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/PaintedItem 2.0"]
+ exports: [
+ "QtQuick/PaintedItem 2.0",
+ "QtQuick/PaintedItem 2.1",
+ "QtQuick/PaintedItem 2.11",
+ "QtQuick/PaintedItem 2.4",
+ "QtQuick/PaintedItem 2.7"
+ ]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "RenderTarget"
values: {
@@ -3207,15 +3591,21 @@ Module {
name: "QQuickParallelAnimation"
defaultProperty: "animations"
prototype: "QQuickAnimationGroup"
- exports: ["QtQuick/ParallelAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/ParallelAnimation 2.0",
+ "QtQuick/ParallelAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
}
Component {
name: "QQuickParentAnimation"
defaultProperty: "animations"
prototype: "QQuickAnimationGroup"
- exports: ["QtQuick/ParentAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/ParentAnimation 2.0",
+ "QtQuick/ParentAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "target"; type: "QQuickItem"; isPointer: true }
Property { name: "newParent"; type: "QQuickItem"; isPointer: true }
Property { name: "via"; type: "QQuickItem"; isPointer: true }
@@ -3258,7 +3648,7 @@ Module {
name: "QQuickPathAngleArc"
prototype: "QQuickCurve"
exports: ["QtQuick/PathAngleArc 2.11"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [11]
Property { name: "centerX"; type: "double" }
Property { name: "centerY"; type: "double" }
Property { name: "radiusX"; type: "double" }
@@ -3270,8 +3660,8 @@ Module {
Component {
name: "QQuickPathAnimation"
prototype: "QQuickAbstractAnimation"
- exports: ["QtQuick/PathAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/PathAnimation 2.0", "QtQuick/PathAnimation 2.12"]
+ exportMetaObjectRevisions: [0, 12]
Enum {
name: "Orientation"
values: {
@@ -3393,15 +3783,15 @@ Module {
name: "QQuickPathMove"
prototype: "QQuickCurve"
exports: ["QtQuick/PathMove 2.9"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [9]
}
Component {
name: "QQuickPathMultiline"
prototype: "QQuickCurve"
exports: ["QtQuick/PathMultiline 2.14"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [14]
Property { name: "start"; type: "QPointF"; isReadonly: true }
- Property { name: "paths"; type: "QVariantList" }
+ Property { name: "paths"; type: "QVariant" }
}
Component {
name: "QQuickPathPercent"
@@ -3414,9 +3804,9 @@ Module {
name: "QQuickPathPolyline"
prototype: "QQuickCurve"
exports: ["QtQuick/PathPolyline 2.14"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [14]
Property { name: "start"; type: "QPointF"; isReadonly: true }
- Property { name: "path"; type: "QVariantList" }
+ Property { name: "path"; type: "QVariant" }
}
Component {
name: "QQuickPathQuad"
@@ -3441,10 +3831,13 @@ Module {
prototype: "QQuickItem"
exports: [
"QtQuick/PathView 2.0",
+ "QtQuick/PathView 2.1",
+ "QtQuick/PathView 2.11",
"QtQuick/PathView 2.13",
+ "QtQuick/PathView 2.4",
"QtQuick/PathView 2.7"
]
- exportMetaObjectRevisions: [0, 13, 7]
+ exportMetaObjectRevisions: [0, 1, 11, 13, 4, 7]
attachedType: "QQuickPathViewAttached"
Enum {
name: "HighlightRangeMode"
@@ -3550,8 +3943,8 @@ Module {
Component {
name: "QQuickPauseAnimation"
prototype: "QQuickAbstractAnimation"
- exports: ["QtQuick/PauseAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/PauseAnimation 2.0", "QtQuick/PauseAnimation 2.12"]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "duration"; type: "int" }
Signal {
name: "durationChanged"
@@ -3597,8 +3990,15 @@ Module {
name: "QQuickPinchArea"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/PinchArea 2.0", "QtQuick/PinchArea 2.5"]
- exportMetaObjectRevisions: [0, 5]
+ exports: [
+ "QtQuick/PinchArea 2.0",
+ "QtQuick/PinchArea 2.1",
+ "QtQuick/PinchArea 2.11",
+ "QtQuick/PinchArea 2.4",
+ "QtQuick/PinchArea 2.5",
+ "QtQuick/PinchArea 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 5, 7]
Property { name: "enabled"; type: "bool" }
Property { name: "pinch"; type: "QQuickPinch"; isReadonly: true; isPointer: true }
Signal {
@@ -3641,7 +4041,7 @@ Module {
name: "QQuickPinchHandler"
prototype: "QQuickMultiPointHandler"
exports: ["QtQuick/PinchHandler 2.12"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Property { name: "minimumScale"; type: "double" }
Property { name: "maximumScale"; type: "double" }
Property { name: "minimumRotation"; type: "double" }
@@ -3662,7 +4062,7 @@ Module {
name: "QQuickPointHandler"
prototype: "QQuickSinglePointHandler"
exports: ["QtQuick/PointHandler 2.12"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Property { name: "translation"; type: "QVector2D"; isReadonly: true }
}
Component {
@@ -3670,7 +4070,7 @@ Module {
prototype: "QObject"
exports: ["QtQuick/PointerDevice 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Enum {
name: "DeviceTypes"
values: {
@@ -3747,7 +4147,7 @@ Module {
prototype: "QObject"
exports: ["QtQuick/PointerEvent 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Property { name: "device"; type: "QQuickPointerDevice"; isReadonly: true; isPointer: true }
Property { name: "modifiers"; type: "Qt::KeyboardModifiers"; isReadonly: true }
Property { name: "button"; type: "Qt::MouseButtons"; isReadonly: true }
@@ -3758,7 +4158,7 @@ Module {
prototype: "QObject"
exports: ["QtQuick/PointerHandler 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Enum {
name: "GrabPermissions"
values: {
@@ -3796,14 +4196,14 @@ Module {
prototype: "QQuickSinglePointEvent"
exports: ["QtQuick/PointerMouseEvent 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
}
Component {
name: "QQuickPointerTouchEvent"
prototype: "QQuickPointerEvent"
exports: ["QtQuick/PointerTouchEvent 2.12"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
}
Component {
name: "QQuickPositionerAttached"
@@ -3815,8 +4215,8 @@ Module {
Component {
name: "QQuickPropertyAction"
prototype: "QQuickAbstractAnimation"
- exports: ["QtQuick/PropertyAction 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/PropertyAction 2.0", "QtQuick/PropertyAction 2.12"]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "target"; type: "QObject"; isPointer: true }
Property { name: "property"; type: "string" }
Property { name: "properties"; type: "string" }
@@ -3835,8 +4235,11 @@ Module {
Component {
name: "QQuickPropertyAnimation"
prototype: "QQuickAbstractAnimation"
- exports: ["QtQuick/PropertyAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/PropertyAnimation 2.0",
+ "QtQuick/PropertyAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "duration"; type: "int" }
Property { name: "from"; type: "QVariant" }
Property { name: "to"; type: "QVariant" }
@@ -3872,8 +4275,14 @@ Module {
name: "QQuickRectangle"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/Rectangle 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/Rectangle 2.0",
+ "QtQuick/Rectangle 2.1",
+ "QtQuick/Rectangle 2.11",
+ "QtQuick/Rectangle 2.4",
+ "QtQuick/Rectangle 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "color"; type: "QColor" }
Property { name: "gradient"; type: "QJSValue" }
Property { name: "border"; type: "QQuickPen"; isReadonly: true; isPointer: true }
@@ -3883,8 +4292,14 @@ Module {
name: "QQuickRepeater"
defaultProperty: "delegate"
prototype: "QQuickItem"
- exports: ["QtQuick/Repeater 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/Repeater 2.0",
+ "QtQuick/Repeater 2.1",
+ "QtQuick/Repeater 2.11",
+ "QtQuick/Repeater 2.4",
+ "QtQuick/Repeater 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "model"; type: "QVariant" }
Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
Property { name: "count"; type: "int"; isReadonly: true }
@@ -3916,8 +4331,11 @@ Module {
Component {
name: "QQuickRotationAnimation"
prototype: "QQuickPropertyAnimation"
- exports: ["QtQuick/RotationAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/RotationAnimation 2.0",
+ "QtQuick/RotationAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Enum {
name: "RotationDirection"
values: {
@@ -3934,8 +4352,11 @@ Module {
Component {
name: "QQuickRotationAnimator"
prototype: "QQuickAnimator"
- exports: ["QtQuick/RotationAnimator 2.2"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/RotationAnimator 2.12",
+ "QtQuick/RotationAnimator 2.2"
+ ]
+ exportMetaObjectRevisions: [12, 2]
Enum {
name: "RotationDirection"
values: {
@@ -3955,8 +4376,16 @@ Module {
name: "QQuickRow"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Row 2.0", "QtQuick/Row 2.6"]
- exportMetaObjectRevisions: [0, 6]
+ exports: [
+ "QtQuick/Row 2.0",
+ "QtQuick/Row 2.1",
+ "QtQuick/Row 2.11",
+ "QtQuick/Row 2.4",
+ "QtQuick/Row 2.6",
+ "QtQuick/Row 2.7",
+ "QtQuick/Row 2.9"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 6, 7, 9]
Property { name: "layoutDirection"; type: "Qt::LayoutDirection" }
Property { name: "effectiveLayoutDirection"; type: "Qt::LayoutDirection"; isReadonly: true }
}
@@ -3974,8 +4403,8 @@ Module {
Component {
name: "QQuickScaleAnimator"
prototype: "QQuickAnimator"
- exports: ["QtQuick/ScaleAnimator 2.2"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/ScaleAnimator 2.12", "QtQuick/ScaleAnimator 2.2"]
+ exportMetaObjectRevisions: [12, 2]
}
Component {
name: "QQuickScaleGrid"
@@ -3993,8 +4422,8 @@ Module {
Component {
name: "QQuickScriptAction"
prototype: "QQuickAbstractAnimation"
- exports: ["QtQuick/ScriptAction 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/ScriptAction 2.0", "QtQuick/ScriptAction 2.12"]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "script"; type: "QQmlScriptString" }
Property { name: "scriptName"; type: "string" }
}
@@ -4002,15 +4431,24 @@ Module {
name: "QQuickSequentialAnimation"
defaultProperty: "animations"
prototype: "QQuickAnimationGroup"
- exports: ["QtQuick/SequentialAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/SequentialAnimation 2.0",
+ "QtQuick/SequentialAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
}
Component {
name: "QQuickShaderEffect"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/ShaderEffect 2.0", "QtQuick/ShaderEffect 2.4"]
- exportMetaObjectRevisions: [0, 4]
+ exports: [
+ "QtQuick/ShaderEffect 2.0",
+ "QtQuick/ShaderEffect 2.1",
+ "QtQuick/ShaderEffect 2.11",
+ "QtQuick/ShaderEffect 2.4",
+ "QtQuick/ShaderEffect 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "CullMode"
values: {
@@ -4050,10 +4488,14 @@ Module {
prototype: "QQuickItem"
exports: [
"QtQuick/ShaderEffectSource 2.0",
+ "QtQuick/ShaderEffectSource 2.1",
+ "QtQuick/ShaderEffectSource 2.11",
+ "QtQuick/ShaderEffectSource 2.4",
"QtQuick/ShaderEffectSource 2.6",
+ "QtQuick/ShaderEffectSource 2.7",
"QtQuick/ShaderEffectSource 2.9"
]
- exportMetaObjectRevisions: [0, 6, 9]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 6, 7, 9]
Enum {
name: "WrapMode"
values: {
@@ -4101,7 +4543,7 @@ Module {
"QtQuick/Shortcut 2.6",
"QtQuick/Shortcut 2.9"
]
- exportMetaObjectRevisions: [0, 6, 9]
+ exportMetaObjectRevisions: [5, 6, 9]
Property { name: "sequence"; type: "QVariant" }
Property { name: "sequences"; revision: 9; type: "QVariantList" }
Property { name: "nativeText"; revision: 6; type: "string"; isReadonly: true }
@@ -4122,8 +4564,11 @@ Module {
Component {
name: "QQuickSmoothedAnimation"
prototype: "QQuickNumberAnimation"
- exports: ["QtQuick/SmoothedAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/SmoothedAnimation 2.0",
+ "QtQuick/SmoothedAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Enum {
name: "ReversingMode"
values: {
@@ -4139,8 +4584,11 @@ Module {
Component {
name: "QQuickSpringAnimation"
prototype: "QQuickNumberAnimation"
- exports: ["QtQuick/SpringAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/SpringAnimation 2.0",
+ "QtQuick/SpringAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "velocity"; type: "double" }
Property { name: "spring"; type: "double" }
Property { name: "damping"; type: "double" }
@@ -4272,8 +4720,14 @@ Module {
name: "QQuickSpriteSequence"
defaultProperty: "sprites"
prototype: "QQuickItem"
- exports: ["QtQuick/SpriteSequence 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/SpriteSequence 2.0",
+ "QtQuick/SpriteSequence 2.1",
+ "QtQuick/SpriteSequence 2.11",
+ "QtQuick/SpriteSequence 2.4",
+ "QtQuick/SpriteSequence 2.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Property { name: "running"; type: "bool" }
Property { name: "interpolate"; type: "bool" }
Property { name: "goalSprite"; type: "string" }
@@ -4431,7 +4885,7 @@ Module {
defaultProperty: "flickableData"
prototype: "QQuickFlickable"
exports: ["QtQuick/TableView 2.12", "QtQuick/TableView 2.14"]
- exportMetaObjectRevisions: [0, 14]
+ exportMetaObjectRevisions: [12, 14]
attachedType: "QQuickTableViewAttached"
Property { name: "rows"; type: "int"; isReadonly: true }
Property { name: "columns"; type: "int"; isReadonly: true }
@@ -4461,7 +4915,7 @@ Module {
name: "QQuickTapHandler"
prototype: "QQuickSinglePointHandler"
exports: ["QtQuick/TapHandler 2.12"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [12]
Enum {
name: "GesturePolicy"
values: {
@@ -4495,14 +4949,17 @@ Module {
prototype: "QQuickImplicitSizeItem"
exports: [
"QtQuick/Text 2.0",
+ "QtQuick/Text 2.1",
"QtQuick/Text 2.10",
- "QtQuick/Text 2.12",
+ "QtQuick/Text 2.11",
"QtQuick/Text 2.2",
"QtQuick/Text 2.3",
+ "QtQuick/Text 2.4",
"QtQuick/Text 2.6",
+ "QtQuick/Text 2.7",
"QtQuick/Text 2.9"
]
- exportMetaObjectRevisions: [0, 10, 12, 2, 3, 6, 9]
+ exportMetaObjectRevisions: [0, 1, 10, 11, 2, 3, 4, 6, 7, 9]
Enum {
name: "HAlignment"
values: {
@@ -4698,12 +5155,14 @@ Module {
"QtQuick/TextEdit 2.0",
"QtQuick/TextEdit 2.1",
"QtQuick/TextEdit 2.10",
+ "QtQuick/TextEdit 2.11",
"QtQuick/TextEdit 2.2",
"QtQuick/TextEdit 2.3",
+ "QtQuick/TextEdit 2.4",
"QtQuick/TextEdit 2.6",
"QtQuick/TextEdit 2.7"
]
- exportMetaObjectRevisions: [0, 1, 10, 2, 3, 6, 7]
+ exportMetaObjectRevisions: [0, 1, 10, 11, 2, 3, 4, 6, 7]
Enum {
name: "HAlignment"
values: {
@@ -4982,13 +5441,15 @@ Module {
prototype: "QQuickImplicitSizeItem"
exports: [
"QtQuick/TextInput 2.0",
+ "QtQuick/TextInput 2.1",
+ "QtQuick/TextInput 2.11",
"QtQuick/TextInput 2.2",
"QtQuick/TextInput 2.4",
"QtQuick/TextInput 2.6",
"QtQuick/TextInput 2.7",
"QtQuick/TextInput 2.9"
]
- exportMetaObjectRevisions: [0, 2, 4, 6, 7, 9]
+ exportMetaObjectRevisions: [0, 1, 11, 2, 4, 6, 7, 9]
Enum {
name: "EchoMode"
values: {
@@ -5238,7 +5699,7 @@ Module {
name: "QQuickTextMetrics"
prototype: "QObject"
exports: ["QtQuick/TextMetrics 2.4"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [4]
Property { name: "font"; type: "QFont" }
Property { name: "text"; type: "string" }
Property { name: "advanceWidth"; type: "double"; isReadonly: true }
@@ -5255,7 +5716,7 @@ Module {
name: "QQuickTouchPoint"
prototype: "QObject"
exports: ["QtQuick/TouchPoint 2.0", "QtQuick/TouchPoint 2.9"]
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 9]
Property { name: "pointId"; type: "int"; isReadonly: true }
Property { name: "uniqueId"; revision: 9; type: "QPointingDeviceUniqueId"; isReadonly: true }
Property { name: "pressed"; type: "bool"; isReadonly: true }
@@ -5301,8 +5762,11 @@ Module {
Component {
name: "QQuickUniformAnimator"
prototype: "QQuickAnimator"
- exports: ["QtQuick/UniformAnimator 2.2"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/UniformAnimator 2.12",
+ "QtQuick/UniformAnimator 2.2"
+ ]
+ exportMetaObjectRevisions: [12, 2]
Property { name: "uniform"; type: "string" }
Signal {
name: "uniformChanged"
@@ -5312,8 +5776,11 @@ Module {
Component {
name: "QQuickVector3dAnimation"
prototype: "QQuickPropertyAnimation"
- exports: ["QtQuick/Vector3dAnimation 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/Vector3dAnimation 2.0",
+ "QtQuick/Vector3dAnimation 2.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "from"; type: "QVector3D" }
Property { name: "to"; type: "QVector3D" }
}
@@ -5371,7 +5838,7 @@ Module {
name: "QQuickWheelHandler"
prototype: "QQuickSinglePointHandler"
exports: ["QtQuick/WheelHandler 2.14"]
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [14]
Property { name: "orientation"; type: "Qt::Orientation" }
Property { name: "invertible"; type: "bool" }
Property { name: "activeTimeout"; type: "double" }
@@ -5403,14 +5870,14 @@ Module {
Component {
name: "QQuickXAnimator"
prototype: "QQuickAnimator"
- exports: ["QtQuick/XAnimator 2.2"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/XAnimator 2.12", "QtQuick/XAnimator 2.2"]
+ exportMetaObjectRevisions: [12, 2]
}
Component {
name: "QQuickYAnimator"
prototype: "QQuickAnimator"
- exports: ["QtQuick/YAnimator 2.2"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/YAnimator 2.12", "QtQuick/YAnimator 2.2"]
+ exportMetaObjectRevisions: [12, 2]
}
Component {
name: "QRegExpValidator"
diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp
index eb7d5027a4..db941d9845 100644
--- a/src/imports/settings/plugin.cpp
+++ b/src/imports/settings/plugin.cpp
@@ -54,7 +54,7 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QByteArray(uri) == QByteArray("Qt.labs.settings"));
- qmlRegisterType<QQmlSettings>(uri, 1, 0, "Settings");
+ qmlRegisterTypesAndRevisions<QQmlSettings>(uri, 1);
qmlRegisterModule(uri, 1, 1); // QTBUG-73239
}
};
diff --git a/src/imports/settings/qqmlsettings.cpp b/src/imports/settings/qqmlsettings.cpp
index 287a70363a..d43f9bafb7 100644
--- a/src/imports/settings/qqmlsettings.cpp
+++ b/src/imports/settings/qqmlsettings.cpp
@@ -473,7 +473,7 @@ QVariant QQmlSettings::value(const QString &key, const QVariant &defaultValue) c
/*!
\qmlmethod Settings::setValue(string key, var value)
- Sets the value of setting key to value. If the key already exists,
+ Sets the value of setting \a key to \a value. If the key already exists,
the previous value is overwritten.
\since Qt 5.12
diff --git a/src/imports/settings/qqmlsettings_p.h b/src/imports/settings/qqmlsettings_p.h
index a86c8b4751..3f1b83f541 100644
--- a/src/imports/settings/qqmlsettings_p.h
+++ b/src/imports/settings/qqmlsettings_p.h
@@ -66,6 +66,7 @@ class QQmlSettings : public QObject, public QQmlParserStatus
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QString category READ category WRITE setCategory FINAL)
Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL)
+ QML_NAMED_ELEMENT(Settings)
public:
explicit QQmlSettings(QObject *parent = 0);
diff --git a/src/imports/shapes/plugin.cpp b/src/imports/shapes/plugin.cpp
index 6197b2fdf5..0b6191d5bb 100644
--- a/src/imports/shapes/plugin.cpp
+++ b/src/imports/shapes/plugin.cpp
@@ -57,20 +57,11 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QByteArray(uri) == QByteArray("QtQuick.Shapes"));
- qmlRegisterType<QQuickShape>(uri, 1, 0, "Shape");
- qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath");
- qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class"));
- qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient");
- qmlRegisterType<QQuickShapeRadialGradient>(uri, 1, 0, "RadialGradient");
- qmlRegisterType<QQuickShapeConicalGradient>(uri, 1, 0, "ConicalGradient");
+ qmlRegisterTypesAndRevisions<QQuickShape, QQuickShapePath, QQuickShapeGradient,
+ QQuickShapeLinearGradient, QQuickShapeRadialGradient,
+ QQuickShapeConicalGradient>(uri, 1);
qmlRegisterModule(uri, 1, 15);
-
- // revision in Qt 5.11: added containsMode property
- qmlRegisterType<QQuickShape, 11>(uri, 1, 11, "Shape");
-
- // revision in Qt 5.14: added scale property
- qmlRegisterType<QQuickShapePath, 14>(uri, 1, 14, "ShapePath"); // QTBUG-61942
}
};
diff --git a/src/imports/shapes/plugins.qmltypes b/src/imports/shapes/plugins.qmltypes
index cd779e7149..fed68b5137 100644
--- a/src/imports/shapes/plugins.qmltypes
+++ b/src/imports/shapes/plugins.qmltypes
@@ -12,8 +12,14 @@ Module {
name: "QQuickShape"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick.Shapes/Shape 1.0", "QtQuick.Shapes/Shape 1.11"]
- exportMetaObjectRevisions: [0, 11]
+ exports: [
+ "QtQuick.Shapes/Shape 1.0",
+ "QtQuick.Shapes/Shape 1.1",
+ "QtQuick.Shapes/Shape 1.11",
+ "QtQuick.Shapes/Shape 1.4",
+ "QtQuick.Shapes/Shape 1.7"
+ ]
+ exportMetaObjectRevisions: [0, 1, 11, 4, 7]
Enum {
name: "RendererType"
values: {
@@ -51,8 +57,11 @@ Module {
name: "QQuickShapeConicalGradient"
defaultProperty: "stops"
prototype: "QQuickShapeGradient"
- exports: ["QtQuick.Shapes/ConicalGradient 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Shapes/ConicalGradient 1.0",
+ "QtQuick.Shapes/ConicalGradient 1.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "centerX"; type: "double" }
Property { name: "centerY"; type: "double" }
Property { name: "angle"; type: "double" }
@@ -61,9 +70,12 @@ Module {
name: "QQuickShapeGradient"
defaultProperty: "stops"
prototype: "QQuickGradient"
- exports: ["QtQuick.Shapes/ShapeGradient 1.0"]
+ exports: [
+ "QtQuick.Shapes/ShapeGradient 1.0",
+ "QtQuick.Shapes/ShapeGradient 1.12"
+ ]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [0, 12]
Enum {
name: "SpreadMode"
values: {
@@ -78,8 +90,11 @@ Module {
name: "QQuickShapeLinearGradient"
defaultProperty: "stops"
prototype: "QQuickShapeGradient"
- exports: ["QtQuick.Shapes/LinearGradient 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Shapes/LinearGradient 1.0",
+ "QtQuick.Shapes/LinearGradient 1.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "x1"; type: "double" }
Property { name: "y1"; type: "double" }
Property { name: "x2"; type: "double" }
@@ -142,8 +157,11 @@ Module {
name: "QQuickShapeRadialGradient"
defaultProperty: "stops"
prototype: "QQuickShapeGradient"
- exports: ["QtQuick.Shapes/RadialGradient 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Shapes/RadialGradient 1.0",
+ "QtQuick.Shapes/RadialGradient 1.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "centerX"; type: "double" }
Property { name: "centerY"; type: "double" }
Property { name: "centerRadius"; type: "double" }
diff --git a/src/imports/statemachine/finalstate.h b/src/imports/statemachine/finalstate.h
index 974d8a8fac..9cdbb51584 100644
--- a/src/imports/statemachine/finalstate.h
+++ b/src/imports/statemachine/finalstate.h
@@ -45,6 +45,7 @@
#include <QtCore/QFinalState>
#include <QtQml/QQmlListProperty>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -54,6 +55,7 @@ class FinalState : public QFinalState
Q_OBJECT
Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged)
Q_CLASSINFO("DefaultProperty", "children")
+ QML_ELEMENT
public:
explicit FinalState(QState *parent = 0);
diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp
index 0ec2c353fc..993e91afea 100644
--- a/src/imports/statemachine/plugin.cpp
+++ b/src/imports/statemachine/plugin.cpp
@@ -42,6 +42,7 @@
#include "state.h"
#include "statemachine.h"
#include "timeouttransition.h"
+#include "statemachineforeign.h"
#include <QHistoryState>
#include <QQmlExtensionPlugin>
@@ -58,15 +59,10 @@ public:
QtQmlStateMachinePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
- qmlRegisterType<State>(uri, 1, 0, "State");
- qmlRegisterType<StateMachine>(uri, 1, 0, "StateMachine");
- qmlRegisterType<QHistoryState>(uri, 1, 0, "HistoryState");
- qmlRegisterType<FinalState>(uri, 1, 0, "FinalState");
- qmlRegisterUncreatableType<QState>(uri, 1, 0, "QState", "Don't use this, use State instead");
- qmlRegisterUncreatableType<QAbstractState>(uri, 1, 0, "QAbstractState", "Don't use this, use State instead");
- qmlRegisterUncreatableType<QSignalTransition>(uri, 1, 0, "QSignalTransition", "Don't use this, use SignalTransition instead");
- qmlRegisterCustomType<SignalTransition>(uri, 1, 0, "SignalTransition", new SignalTransitionParser);
- qmlRegisterType<TimeoutTransition>(uri, 1, 0, "TimeoutTransition");
+ qmlRegisterTypesAndRevisions<
+ State, StateMachine, FinalState, TimeoutTransition, SignalTransition,
+ QHistoryStateForeign, QStateForeign, QAbstractStateForeign, QSignalTransitionForeign
+ >(uri, 1);
qmlProtectModule(uri, 1);
qmlRegisterModule(uri, 1, 15);
diff --git a/src/imports/statemachine/plugins.qmltypes b/src/imports/statemachine/plugins.qmltypes
index 541b1cc114..206159f057 100644
--- a/src/imports/statemachine/plugins.qmltypes
+++ b/src/imports/statemachine/plugins.qmltypes
@@ -137,8 +137,11 @@ Module {
Component {
name: "SignalTransition"
prototype: "QSignalTransition"
- exports: ["QtQml.StateMachine/SignalTransition 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQml.StateMachine/SignalTransition 1.0",
+ "QtQml.StateMachine/SignalTransition 1.1"
+ ]
+ exportMetaObjectRevisions: [0, 1]
Property { name: "signal"; type: "QJSValue" }
Property { name: "guard"; type: "QQmlScriptString" }
Signal { name: "invokeYourself" }
@@ -166,8 +169,11 @@ Module {
Component {
name: "TimeoutTransition"
prototype: "QSignalTransition"
- exports: ["QtQml.StateMachine/TimeoutTransition 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQml.StateMachine/TimeoutTransition 1.0",
+ "QtQml.StateMachine/TimeoutTransition 1.1"
+ ]
+ exportMetaObjectRevisions: [0, 1]
Property { name: "timeout"; type: "int" }
}
}
diff --git a/src/imports/statemachine/signaltransition.h b/src/imports/statemachine/signaltransition.h
index f005c5e9b1..748e230b3e 100644
--- a/src/imports/statemachine/signaltransition.h
+++ b/src/imports/statemachine/signaltransition.h
@@ -57,6 +57,7 @@ class SignalTransition : public QSignalTransition, public QQmlParserStatus
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QJSValue signal READ signal WRITE setSignal NOTIFY qmlSignalChanged)
Q_PROPERTY(QQmlScriptString guard READ guard WRITE setGuard NOTIFY guardChanged)
+ QML_ELEMENT
public:
explicit SignalTransition(QState *parent = nullptr);
@@ -101,6 +102,12 @@ public:
void applyBindings(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
+template<>
+inline QQmlCustomParser *qmlCreateCustomParser<SignalTransition>()
+{
+ return new SignalTransitionParser;
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/imports/statemachine/state.h b/src/imports/statemachine/state.h
index 8e8cefab19..4b17ea0e5f 100644
--- a/src/imports/statemachine/state.h
+++ b/src/imports/statemachine/state.h
@@ -45,6 +45,7 @@
#include <QtCore/QState>
#include <QtQml/QQmlParserStatus>
#include <QtQml/QQmlListProperty>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -54,6 +55,7 @@ class State : public QState, public QQmlParserStatus
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged)
Q_CLASSINFO("DefaultProperty", "children")
+ QML_ELEMENT
public:
explicit State(QState *parent = 0);
diff --git a/src/imports/statemachine/statemachine.h b/src/imports/statemachine/statemachine.h
index 1fa7a9da43..04894477b3 100644
--- a/src/imports/statemachine/statemachine.h
+++ b/src/imports/statemachine/statemachine.h
@@ -45,6 +45,7 @@
#include <QtCore/QStateMachine>
#include <QtQml/QQmlParserStatus>
#include <QtQml/QQmlListProperty>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -58,6 +59,7 @@ class StateMachine : public QStateMachine, public QQmlParserStatus
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY qmlRunningChanged)
Q_CLASSINFO("DefaultProperty", "children")
+ QML_ELEMENT
public:
explicit StateMachine(QObject *parent = 0);
diff --git a/src/imports/statemachine/statemachine.pro b/src/imports/statemachine/statemachine.pro
index 926a9d4a5e..7affc768e2 100644
--- a/src/imports/statemachine/statemachine.pro
+++ b/src/imports/statemachine/statemachine.pro
@@ -19,6 +19,7 @@ HEADERS = \
$$PWD/signaltransition.h \
$$PWD/state.h \
$$PWD/statemachine.h \
- $$PWD/timeouttransition.h
+ $$PWD/timeouttransition.h \
+ $$PWD/statemachineforeign.h
load(qml_plugin)
diff --git a/src/imports/statemachine/statemachineforeign.h b/src/imports/statemachine/statemachineforeign.h
new file mode 100644
index 0000000000..363c9d0e31
--- /dev/null
+++ b/src/imports/statemachine/statemachineforeign.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 STATEMACHINEFOREIGN_H
+#define STATEMACHINEFOREIGN_H
+
+#include <QtQml/qqml.h>
+#include <QtCore/qhistorystate.h>
+#include <QtCore/qstate.h>
+#include <QtCore/qabstractstate.h>
+#include <QtCore/qsignaltransition.h>
+
+struct QHistoryStateForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QHistoryState)
+ QML_NAMED_ELEMENT(HistoryState)
+};
+
+struct QStateForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QState)
+ QML_NAMED_ELEMENT(QState)
+ QML_UNCREATABLE("Don't use this, use State instead.")
+};
+
+struct QAbstractStateForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QAbstractState)
+ QML_NAMED_ELEMENT(QAbstractState)
+ QML_UNCREATABLE("Don't use this, use State instead.")
+};
+
+struct QSignalTransitionForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QSignalTransition)
+ QML_NAMED_ELEMENT(QSignalTransition)
+ QML_UNCREATABLE("Don't use this, use SignalTransition instead.")
+};
+
+#endif // STATEMACHINEFOREIGN_H
diff --git a/src/imports/statemachine/timeouttransition.h b/src/imports/statemachine/timeouttransition.h
index 2fc850fc70..cc3a22e0e5 100644
--- a/src/imports/statemachine/timeouttransition.h
+++ b/src/imports/statemachine/timeouttransition.h
@@ -42,6 +42,7 @@
#include <QtCore/QSignalTransition>
#include <QtQml/QQmlParserStatus>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
class QTimer;
@@ -51,6 +52,7 @@ class TimeoutTransition : public QSignalTransition, public QQmlParserStatus
Q_OBJECT
Q_PROPERTY(int timeout READ timeout WRITE setTimeout NOTIFY timeoutChanged)
Q_INTERFACES(QQmlParserStatus)
+ QML_ELEMENT
public:
TimeoutTransition(QState *parent = nullptr);
diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index a8bcfa2764..86f0dd6dc7 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -37,99 +37,15 @@
**
****************************************************************************/
-#include <private/qv4scopedvalue_p.h>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
-#include <QtQml/qjsvalue.h>
-#include <QtQml/qjsengine.h>
-#include "QtQuickTest/private/quicktestresult_p.h"
-#include "QtQuickTest/private/quicktestevent_p.h"
-#include "private/qtestoptions_p.h"
-#include "QtQuick/qquickitem.h"
-#include <QtQml/private/qqmlengine_p.h>
-#include <QtGui/QGuiApplication>
-#include <QtGui/qstylehints.h>
+#include <QtQuickTest/private/quicktestresult_p.h>
+#include <QtQuickTest/private/quicktestevent_p.h>
+#include <QtQuickTest/private/quicktestutil_p.h>
+#include <QtQuickTest/private/qtestoptions_p.h>
QML_DECLARE_TYPE(QuickTestResult)
QML_DECLARE_TYPE(QuickTestEvent)
-
-#include <QtDebug>
-
-QT_BEGIN_NAMESPACE
-
-class QuickTestUtil : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool printAvailableFunctions READ printAvailableFunctions NOTIFY printAvailableFunctionsChanged)
- Q_PROPERTY(int dragThreshold READ dragThreshold NOTIFY dragThresholdChanged)
-public:
- QuickTestUtil(QObject *parent = nullptr)
- :QObject(parent)
- {}
-
- ~QuickTestUtil() override
- {}
- bool printAvailableFunctions() const
- {
- return QTest::printAvailableFunctions;
- }
- int dragThreshold() const { return QGuiApplication::styleHints()->startDragDistance(); }
-
-Q_SIGNALS:
- void printAvailableFunctionsChanged();
- void dragThresholdChanged();
-
-public Q_SLOTS:
-
- QJSValue typeName(const QVariant& v) const
- {
- QString name(v.typeName());
- if (v.canConvert<QObject*>()) {
- QQmlType type;
- const QMetaObject *mo = v.value<QObject*>()->metaObject();
- while (!type.isValid() && mo) {
- type = QQmlMetaType::qmlType(mo);
- mo = mo->superClass();
- }
- if (type.isValid()) {
- name = type.qmlTypeName();
- }
- }
-
- QQmlEngine *engine = qmlEngine(this);
- QV4::ExecutionEngine *v4 = engine->handle();
- return QJSValue(v4, v4->newString(name)->asReturnedValue());
- }
-
- bool compare(const QVariant& act, const QVariant& exp) const {
- return act == exp;
- }
-
- QJSValue callerFile(int frameIndex = 0) const
- {
- QQmlEngine *engine = qmlEngine(this);
- QV4::ExecutionEngine *v4 = engine->handle();
- QV4::Scope scope(v4);
-
- QVector<QV4::StackFrame> stack = v4->stackTrace(frameIndex + 2);
- return (stack.size() > frameIndex + 1)
- ? QJSValue(v4, v4->newString(stack.at(frameIndex + 1).source)->asReturnedValue())
- : QJSValue();
- }
- int callerLine(int frameIndex = 0) const
- {
- QQmlEngine *engine = qmlEngine(this);
- QV4::ExecutionEngine *v4 = engine->handle();
-
- QVector<QV4::StackFrame> stack = v4->stackTrace(frameIndex + 2);
- if (stack.size() > frameIndex + 1)
- return stack.at(frameIndex + 1).line;
- return -1;
- }
-};
-
-QT_END_NAMESPACE
-
QML_DECLARE_TYPE(QuickTestUtil)
QT_BEGIN_NAMESPACE
@@ -144,13 +60,8 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtTest"));
- qmlRegisterType<QuickTestResult, 0>(uri,1,0,"TestResult");
- qmlRegisterType<QuickTestResult, 1>(uri,1,1,"TestResult");
- qmlRegisterType<QuickTestResult, 13>(uri,1,13,"TestResult");
- qmlRegisterType<QuickTestEvent>(uri,1,0,"TestEvent");
- qmlRegisterType<QuickTestEvent>(uri,1,2,"TestEvent");
- qmlRegisterType<QuickTestUtil>(uri,1,0,"TestUtil");
- qmlRegisterAnonymousType<QQuickTouchEventSequence>(uri);
+ qmlRegisterTypesAndRevisions<QuickTestResult, QuickTestEvent,
+ QuickTestUtil, QQuickTouchEventSequence>(uri, 1);
qmlRegisterModule(uri, 1, 15);
}
diff --git a/src/imports/testlib/plugins.qmltypes b/src/imports/testlib/plugins.qmltypes
index 6a1371e5f1..0491079e86 100644
--- a/src/imports/testlib/plugins.qmltypes
+++ b/src/imports/testlib/plugins.qmltypes
@@ -46,7 +46,7 @@ Module {
name: "QuickTestEvent"
prototype: "QObject"
exports: ["QtTest/TestEvent 1.0", "QtTest/TestEvent 1.2"]
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 2]
Property { name: "defaultMouseDelay"; type: "int"; isReadonly: true }
Method {
name: "keyPress"
diff --git a/src/imports/wavefrontmesh/plugin.cpp b/src/imports/wavefrontmesh/plugin.cpp
index c695b5d19c..937d3a8ff0 100644
--- a/src/imports/wavefrontmesh/plugin.cpp
+++ b/src/imports/wavefrontmesh/plugin.cpp
@@ -57,7 +57,7 @@ public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.wavefrontmesh"));
- qmlRegisterType<QWavefrontMesh>(uri, 1, 0, "WavefrontMesh");
+ qmlRegisterTypesAndRevisions<QWavefrontMesh>(uri, 1);
qmlRegisterModule(uri, 1, 15);
}
diff --git a/src/imports/wavefrontmesh/qwavefrontmesh.h b/src/imports/wavefrontmesh/qwavefrontmesh.h
index e3ded8078e..a8a40c1a6a 100644
--- a/src/imports/wavefrontmesh/qwavefrontmesh.h
+++ b/src/imports/wavefrontmesh/qwavefrontmesh.h
@@ -55,6 +55,8 @@ class QWavefrontMesh : public QQuickShaderEffectMesh
Q_PROPERTY(Error lastError READ lastError NOTIFY lastErrorChanged)
Q_PROPERTY(QVector3D projectionPlaneV READ projectionPlaneV WRITE setProjectionPlaneV NOTIFY projectionPlaneVChanged)
Q_PROPERTY(QVector3D projectionPlaneW READ projectionPlaneW WRITE setProjectionPlaneW NOTIFY projectionPlaneWChanged)
+ QML_NAMED_ELEMENT(WavefrontMesh)
+
public:
enum Error {
NoError,
diff --git a/src/imports/window/plugins.qmltypes b/src/imports/window/plugins.qmltypes
index 82b7ce0fc5..5d6cf33f4f 100644
--- a/src/imports/window/plugins.qmltypes
+++ b/src/imports/window/plugins.qmltypes
@@ -24,9 +24,13 @@ Module {
Component {
name: "QQuickScreen"
prototype: "QObject"
- exports: ["QtQuick.Window/Screen 2.0", "QtQuick.Window/Screen 2.3"]
+ exports: [
+ "QtQuick.Window/Screen 2.0",
+ "QtQuick.Window/Screen 2.10",
+ "QtQuick.Window/Screen 2.3"
+ ]
isCreatable: false
- exportMetaObjectRevisions: [0, 3]
+ exportMetaObjectRevisions: [0, 10, 3]
attachedType: "QQuickScreenAttached"
}
Component {
@@ -100,6 +104,12 @@ Module {
"NativeTextRendering": 1
}
}
+ Enum {
+ name: "NativeObjectType"
+ values: {
+ "NativeObjectTexture": 0
+ }
+ }
Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "color"; type: "QColor" }
Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }
@@ -163,10 +173,11 @@ Module {
exports: [
"QtQuick.Window/Window 2.1",
"QtQuick.Window/Window 2.13",
+ "QtQuick.Window/Window 2.14",
"QtQuick.Window/Window 2.2",
"QtQuick.Window/Window 2.3"
]
- exportMetaObjectRevisions: [0, 13, 2, 3]
+ exportMetaObjectRevisions: [1, 13, 14, 2, 3]
attachedType: "QQuickWindowAttached"
Property { name: "visible"; type: "bool" }
Property { name: "visibility"; type: "Visibility" }
diff --git a/src/particles/qquickage_p.h b/src/particles/qquickage_p.h
index 5db6167dc1..890c6a63c1 100644
--- a/src/particles/qquickage_p.h
+++ b/src/particles/qquickage_p.h
@@ -59,6 +59,7 @@ class QQuickAgeAffector : public QQuickParticleAffector
Q_OBJECT
Q_PROPERTY(int lifeLeft READ lifeLeft WRITE setLifeLeft NOTIFY lifeLeftChanged)
Q_PROPERTY(bool advancePosition READ advancePosition WRITE setAdvancePosition NOTIFY advancePositionChanged)
+ QML_NAMED_ELEMENT(Age)
public:
explicit QQuickAgeAffector(QQuickItem *parent = 0);
diff --git a/src/particles/qquickangledirection_p.h b/src/particles/qquickangledirection_p.h
index 66290fb19e..d0fdf5a68c 100644
--- a/src/particles/qquickangledirection_p.h
+++ b/src/particles/qquickangledirection_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
#include "qquickdirection_p.h"
+#include <QtQml/qqml.h>
+
QT_BEGIN_NAMESPACE
class QQuickAngleDirection : public QQuickDirection
@@ -60,6 +62,7 @@ class QQuickAngleDirection : public QQuickDirection
Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
Q_PROPERTY(qreal angleVariation READ angleVariation WRITE setAngleVariation NOTIFY angleVariationChanged)
Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
+ QML_NAMED_ELEMENT(AngleDirection)
public:
explicit QQuickAngleDirection(QObject *parent = 0);
QPointF sample(const QPointF &from) override;
diff --git a/src/particles/qquickcumulativedirection_p.h b/src/particles/qquickcumulativedirection_p.h
index 39f8ab8a24..5160d8f09a 100644
--- a/src/particles/qquickcumulativedirection_p.h
+++ b/src/particles/qquickcumulativedirection_p.h
@@ -52,6 +52,8 @@
//
#include "qquickdirection_p.h"
#include <QQmlListProperty>
+#include <QtQml/qqml.h>
+
QT_BEGIN_NAMESPACE
class QQuickCumulativeDirection : public QQuickDirection
@@ -59,6 +61,7 @@ class QQuickCumulativeDirection : public QQuickDirection
Q_OBJECT
Q_PROPERTY(QQmlListProperty<QQuickDirection> directions READ directions)
Q_CLASSINFO("DefaultProperty", "directions")
+ QML_NAMED_ELEMENT(CumulativeDirection)
public:
explicit QQuickCumulativeDirection(QObject *parent = 0);
QQmlListProperty<QQuickDirection> directions();
diff --git a/src/particles/qquickcustomaffector.cpp b/src/particles/qquickcustomaffector.cpp
index cadd2992b1..5e2133dfaf 100644
--- a/src/particles/qquickcustomaffector.cpp
+++ b/src/particles/qquickcustomaffector.cpp
@@ -233,7 +233,7 @@ bool QQuickCustomAffector::affectParticle(QQuickParticleData *d, qreal dt)
return changed;
}
-void QQuickCustomAffector::affectProperties(const QList<QQuickParticleData*> particles, qreal dt)
+void QQuickCustomAffector::affectProperties(const QList<QQuickParticleData*> &particles, qreal dt)
{
foreach (QQuickParticleData* d, particles)
if ( affectParticle(d, dt) )
diff --git a/src/particles/qquickcustomaffector_p.h b/src/particles/qquickcustomaffector_p.h
index 10db70d71d..5e8671514d 100644
--- a/src/particles/qquickcustomaffector_p.h
+++ b/src/particles/qquickcustomaffector_p.h
@@ -52,6 +52,7 @@
//
#include <QObject>
+#include <QtQml/qqml.h>
#include "qquickparticlesystem_p.h"
#include "qquickparticleextruder_p.h"
#include "qquickparticleaffector_p.h"
@@ -66,6 +67,7 @@ class QQuickCustomAffector : public QQuickParticleAffector
Q_PROPERTY(QQuickDirection *position READ position WRITE setPosition NOTIFY positionChanged RESET positionReset)
Q_PROPERTY(QQuickDirection *velocity READ velocity WRITE setVelocity NOTIFY velocityChanged RESET velocityReset)
Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged RESET accelerationReset)
+ QML_NAMED_ELEMENT(Affector)
public:
explicit QQuickCustomAffector(QQuickItem *parent = 0);
@@ -156,7 +158,7 @@ protected:
bool affectParticle(QQuickParticleData *d, qreal dt) override;
private:
- void affectProperties(const QList<QQuickParticleData*> particles, qreal dt);
+ void affectProperties(const QList<QQuickParticleData*> &particles, qreal dt);
QQuickDirection * m_position;
QQuickDirection * m_velocity;
QQuickDirection * m_acceleration;
diff --git a/src/particles/qquickcustomparticle_p.h b/src/particles/qquickcustomparticle_p.h
index e2292cb33b..444f7ad215 100644
--- a/src/particles/qquickcustomparticle_p.h
+++ b/src/particles/qquickcustomparticle_p.h
@@ -67,6 +67,7 @@ class QQuickCustomParticle : public QQuickParticlePainter
Q_OBJECT
Q_PROPERTY(QByteArray fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
Q_PROPERTY(QByteArray vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
+ QML_NAMED_ELEMENT(CustomParticle)
public:
explicit QQuickCustomParticle(QQuickItem* parent=0);
diff --git a/src/particles/qquickdirection_p.h b/src/particles/qquickdirection_p.h
index 10960f9920..60b4d8eb1d 100644
--- a/src/particles/qquickdirection_p.h
+++ b/src/particles/qquickdirection_p.h
@@ -53,12 +53,16 @@
#include <QObject>
#include <QPointF>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
class QQuickDirection : public QObject
{
Q_OBJECT
+ QML_NAMED_ELEMENT(NullVector)
+ QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.")
+
public:
explicit QQuickDirection(QObject *parent = 0);
diff --git a/src/particles/qquickellipseextruder_p.h b/src/particles/qquickellipseextruder_p.h
index 0af7f4d94f..c92443fedf 100644
--- a/src/particles/qquickellipseextruder_p.h
+++ b/src/particles/qquickellipseextruder_p.h
@@ -58,6 +58,7 @@ class QQuickEllipseExtruder : public QQuickParticleExtruder
{
Q_OBJECT
Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)//###Use base class? If it's still box
+ QML_NAMED_ELEMENT(EllipseShape)
public:
explicit QQuickEllipseExtruder(QObject *parent = 0);
QPointF extrude(const QRectF &) override;
diff --git a/src/particles/qquickfriction_p.h b/src/particles/qquickfriction_p.h
index 05ae7a38d5..5686bb37d5 100644
--- a/src/particles/qquickfriction_p.h
+++ b/src/particles/qquickfriction_p.h
@@ -59,6 +59,7 @@ class QQuickFrictionAffector : public QQuickParticleAffector
Q_OBJECT
Q_PROPERTY(qreal factor READ factor WRITE setFactor NOTIFY factorChanged)
Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged)
+ QML_NAMED_ELEMENT(Friction)
public:
explicit QQuickFrictionAffector(QQuickItem *parent = 0);
diff --git a/src/particles/qquickgravity_p.h b/src/particles/qquickgravity_p.h
index 333d3d1534..ef7cc770b7 100644
--- a/src/particles/qquickgravity_p.h
+++ b/src/particles/qquickgravity_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
#include "qquickparticleaffector_p.h"
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +61,7 @@ class QQuickGravityAffector : public QQuickParticleAffector
Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
Q_PROPERTY(qreal acceleration READ magnitude WRITE setAcceleration NOTIFY magnitudeChanged)
Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
+ QML_NAMED_ELEMENT(Gravity)
public:
explicit QQuickGravityAffector(QQuickItem *parent = 0);
qreal magnitude() const;
diff --git a/src/particles/qquickgroupgoal_p.h b/src/particles/qquickgroupgoal_p.h
index 9a56ef5cce..022b244ed7 100644
--- a/src/particles/qquickgroupgoal_p.h
+++ b/src/particles/qquickgroupgoal_p.h
@@ -61,6 +61,7 @@ class QQuickGroupGoalAffector : public QQuickParticleAffector
Q_OBJECT
Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged)
+ QML_NAMED_ELEMENT(GroupGoal)
public:
explicit QQuickGroupGoalAffector(QQuickItem *parent = 0);
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index 649fbb30c2..bd3865f42f 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -179,7 +179,7 @@ public:
setShaderFileName(FragmentStage, QStringLiteral(":/particles/shaders_ng/imageparticle_tabled.frag.qsb"));
}
- bool updateUniformData(const RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
+ bool updateUniformData(RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
{
QByteArray *buf = renderState.uniformData();
Q_ASSERT(buf->size() >= 80 + 2 * (UNIFORM_ARRAY_SIZE * 4 * 4));
@@ -216,7 +216,7 @@ public:
return true;
}
- void updateSampledImage(const RenderState &renderState, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &renderState, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *) override
{
ImageMaterialData *state = static_cast<ImageMaterial *>(newMaterial)->state();
@@ -331,7 +331,7 @@ public:
setShaderFileName(FragmentStage, QStringLiteral(":/particles/shaders_ng/imageparticle_deformed.frag.qsb"));
}
- bool updateUniformData(const RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
+ bool updateUniformData(RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
{
QByteArray *buf = renderState.uniformData();
Q_ASSERT(buf->size() >= 80 + 2 * (UNIFORM_ARRAY_SIZE * 4 * 4));
@@ -357,7 +357,7 @@ public:
return true;
}
- void updateSampledImage(const RenderState &renderState, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &renderState, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *) override
{
ImageMaterialData *state = static_cast<ImageMaterial *>(newMaterial)->state();
@@ -487,7 +487,7 @@ public:
setShaderFileName(FragmentStage, QStringLiteral(":/particles/shaders_ng/imageparticle_sprite.frag.qsb"));
}
- bool updateUniformData(const RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
+ bool updateUniformData(RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
{
QByteArray *buf = renderState.uniformData();
Q_ASSERT(buf->size() >= 80 + 2 * (UNIFORM_ARRAY_SIZE * 4 * 4));
@@ -524,7 +524,7 @@ public:
return true;
}
- void updateSampledImage(const RenderState &renderState, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &renderState, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *) override
{
ImageMaterialData *state = static_cast<ImageMaterial *>(newMaterial)->state();
@@ -651,7 +651,7 @@ public:
setShaderFileName(FragmentStage, QStringLiteral(":/particles/shaders_ng/imageparticle_colored.frag.qsb"));
}
- bool updateUniformData(const RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
+ bool updateUniformData(RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
{
QByteArray *buf = renderState.uniformData();
Q_ASSERT(buf->size() >= 80 + 2 * (UNIFORM_ARRAY_SIZE * 4 * 4));
@@ -677,7 +677,7 @@ public:
return true;
}
- void updateSampledImage(const RenderState &renderState, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &renderState, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *) override
{
ImageMaterialData *state = static_cast<ImageMaterial *>(newMaterial)->state();
@@ -799,7 +799,7 @@ public:
setShaderFileName(FragmentStage, QStringLiteral(":/particles/shaders_ng/imageparticle_simple.frag.qsb"));
}
- bool updateUniformData(const RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
+ bool updateUniformData(RenderState &renderState, QSGMaterial *newMaterial, QSGMaterial *) override
{
QByteArray *buf = renderState.uniformData();
Q_ASSERT(buf->size() >= 80 + 2 * (UNIFORM_ARRAY_SIZE * 4 * 4));
@@ -825,7 +825,7 @@ public:
return true;
}
- void updateSampledImage(const RenderState &renderState, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &renderState, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *) override
{
ImageMaterialData *state = static_cast<ImageMaterial *>(newMaterial)->state();
diff --git a/src/particles/qquickimageparticle_p.h b/src/particles/qquickimageparticle_p.h
index 059cf67019..83fc75e9c9 100644
--- a/src/particles/qquickimageparticle_p.h
+++ b/src/particles/qquickimageparticle_p.h
@@ -202,6 +202,7 @@ class QQuickImageParticle : public QQuickParticlePainter
Q_PROPERTY(bool spritesInterpolate READ spritesInterpolate WRITE setSpritesInterpolate NOTIFY spritesInterpolateChanged)
Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
+ QML_NAMED_ELEMENT(ImageParticle)
public:
explicit QQuickImageParticle(QQuickItem *parent = 0);
virtual ~QQuickImageParticle();
diff --git a/src/particles/qquickitemparticle.cpp b/src/particles/qquickitemparticle.cpp
index e68ea54707..fc28864746 100644
--- a/src/particles/qquickitemparticle.cpp
+++ b/src/particles/qquickitemparticle.cpp
@@ -59,32 +59,38 @@ QT_BEGIN_NAMESPACE
/*!
\qmlmethod QtQuick.Particles::ItemParticle::freeze(Item item)
- Suspends the flow of time for the logical particle which item represents, allowing you to control its movement.
+ Suspends the flow of time for the logical particle which \a item represents,
+ allowing you to control its movement.
*/
/*!
\qmlmethod QtQuick.Particles::ItemParticle::unfreeze(Item item)
- Restarts the flow of time for the logical particle which item represents, allowing it to be moved by the particle system again.
+ Restarts the flow of time for the logical particle which \a item represents,
+ allowing it to be moved by the particle system again.
*/
/*!
\qmlmethod QtQuick.Particles::ItemParticle::take(Item item, bool prioritize)
- Asks the ItemParticle to take over control of item positioning temporarily.
+ Asks the ItemParticle to take over control of \a item positioning temporarily.
It will follow the movement of a logical particle when one is available.
- By default items form a queue when waiting for a logical particle, but if prioritize is true then it will go immediately to the
- head of the queue.
+ By default items form a queue when waiting for a logical particle, but if
+ \a prioritize is \c true, then it will go immediately to the head of the
+ queue.
ItemParticle does not take ownership of the item, and will relinquish
control when the logical particle expires. Commonly at this point you will
want to put it back in the queue, you can do this with the below line in
the delegate definition:
+
\code
ItemParticle.onDetached: itemParticleInstance.take(delegateRootItem);
\endcode
+
or delete it, such as with the below line in the delegate definition:
+
\code
ItemParticle.onDetached: delegateRootItem.destroy();
\endcode
@@ -93,7 +99,9 @@ QT_BEGIN_NAMESPACE
/*!
\qmlmethod QtQuick.Particles::ItemParticle::give(Item item)
- Orders the ItemParticle to give you control of the item. It will cease controlling it and the item will lose its association to the logical particle.
+ Orders the ItemParticle to give you control of the \a item. It will cease
+ controlling it and the item will lose its association to the logical
+ particle.
*/
/*!
diff --git a/src/particles/qquickitemparticle_p.h b/src/particles/qquickitemparticle_p.h
index 7867add4e4..70cfe2a446 100644
--- a/src/particles/qquickitemparticle_p.h
+++ b/src/particles/qquickitemparticle_p.h
@@ -63,6 +63,8 @@ class QQuickItemParticle : public QQuickParticlePainter
Q_OBJECT
Q_PROPERTY(bool fade READ fade WRITE setFade NOTIFY fadeChanged)
Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ QML_NAMED_ELEMENT(ItemParticle)
+ QML_ATTACHED(QQuickItemParticleAttached)
public:
explicit QQuickItemParticle(QQuickItem *parent = 0);
~QQuickItemParticle();
@@ -143,6 +145,4 @@ Q_SIGNALS:
QT_END_NAMESPACE
-QML_DECLARE_TYPEINFO(QQuickItemParticle, QML_HAS_ATTACHED_PROPERTIES)
-
#endif // ITEMPARTICLE_H
diff --git a/src/particles/qquicklineextruder_p.h b/src/particles/qquicklineextruder_p.h
index 306f3a1dd6..76ac5aaf11 100644
--- a/src/particles/qquicklineextruder_p.h
+++ b/src/particles/qquicklineextruder_p.h
@@ -57,6 +57,7 @@ class QQuickLineExtruder : public QQuickParticleExtruder
Q_OBJECT
//Default is topleft to bottom right. Flipped makes it topright to bottom left
Q_PROPERTY(bool mirrored READ mirrored WRITE setMirrored NOTIFY mirroredChanged)
+ QML_NAMED_ELEMENT(LineShape)
public:
explicit QQuickLineExtruder(QObject *parent = 0);
diff --git a/src/particles/qquickmaskextruder.cpp b/src/particles/qquickmaskextruder.cpp
index 4c5d9e9d88..2ce3650743 100644
--- a/src/particles/qquickmaskextruder.cpp
+++ b/src/particles/qquickmaskextruder.cpp
@@ -68,14 +68,14 @@ QQuickMaskExtruder::QQuickMaskExtruder(QObject *parent) :
{
}
-void QQuickMaskExtruder::setSource(QUrl arg)
+void QQuickMaskExtruder::setSource(const QUrl &arg)
{
if (m_source != arg) {
m_source = arg;
m_lastHeight = -1;//Trigger reset
m_lastWidth = -1;
- emit sourceChanged(arg);
+ emit sourceChanged(m_source);
startMaskLoading();
}
}
diff --git a/src/particles/qquickmaskextruder_p.h b/src/particles/qquickmaskextruder_p.h
index 0fc0331db8..419d162811 100644
--- a/src/particles/qquickmaskextruder_p.h
+++ b/src/particles/qquickmaskextruder_p.h
@@ -61,6 +61,7 @@ class QQuickMaskExtruder : public QQuickParticleExtruder
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ QML_NAMED_ELEMENT(MaskShape)
public:
explicit QQuickMaskExtruder(QObject *parent = 0);
QPointF extrude(const QRectF &) override;
@@ -73,10 +74,10 @@ public:
Q_SIGNALS:
- void sourceChanged(QUrl arg);
+ void sourceChanged(const QUrl &arg);
public Q_SLOTS:
- void setSource(QUrl arg);
+ void setSource(const QUrl &arg);
private Q_SLOTS:
void startMaskLoading();
diff --git a/src/particles/qquickparticleaffector.cpp b/src/particles/qquickparticleaffector.cpp
index 3d6035c577..ffbd5674f0 100644
--- a/src/particles/qquickparticleaffector.cpp
+++ b/src/particles/qquickparticleaffector.cpp
@@ -125,7 +125,7 @@ QT_BEGIN_NAMESPACE
themselves). As this executes JavaScript code per particle, it is not recommended to use this
signal with a high-volume particle system.
- x,y is the particle's current position.
+ (\a {x}, \a {y}) is the particle's current position.
The corresponding handler is \c onAffected.
*/
diff --git a/src/particles/qquickparticleaffector_p.h b/src/particles/qquickparticleaffector_p.h
index 5c9652bc32..fd4887333e 100644
--- a/src/particles/qquickparticleaffector_p.h
+++ b/src/particles/qquickparticleaffector_p.h
@@ -68,6 +68,9 @@ class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleAffector : public QQuickItem
Q_PROPERTY(bool once READ onceOff WRITE setOnceOff NOTIFY onceChanged)
Q_PROPERTY(QQuickParticleExtruder* shape READ shape WRITE setShape NOTIFY shapeChanged)
+ QML_NAMED_ELEMENT(ParticleAffector)
+ QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.")
+
public:
explicit QQuickParticleAffector(QQuickItem *parent = 0);
virtual void affectSystem(qreal dt);
diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp
index 4e36ad149a..c0d9fa941d 100644
--- a/src/particles/qquickparticleemitter.cpp
+++ b/src/particles/qquickparticleemitter.cpp
@@ -191,10 +191,10 @@ QT_BEGIN_NAMESPACE
/*!
\qmlsignal QtQuick.Particles::Emitter::emitParticles(Array particles)
- This signal is emitted when particles are emitted. particles is a JavaScript
+ This signal is emitted when particles are emitted. \a particles is a JavaScript
array of Particle objects. You can modify particle attributes directly within the handler.
- Note that JavaScript is slower to execute, so it is not recommended to use this in
+ \note JavaScript is slower to execute, so it is not recommended to use this in
high-volume particle systems.
The corresponding handler is \c onEmitParticles.
@@ -202,19 +202,20 @@ QT_BEGIN_NAMESPACE
/*! \qmlmethod QtQuick.Particles::Emitter::burst(int count)
- Emits count particles from this emitter immediately.
+ Emits a number of particles, specified by \a count, from this emitter immediately.
*/
/*! \qmlmethod QtQuick.Particles::Emitter::burst(int count, int x, int y)
- Emits count particles from this emitter immediately. The particles are emitted
- as if the Emitter was positioned at x,y but all other properties are the same.
+ Emits a number of particles, specified by \a count, from this emitter immediately.
+ The particles are emitted as if the Emitter was positioned at (\a {x}, \a {y}) but
+ all other properties are the same.
*/
/*! \qmlmethod QtQuick.Particles::Emitter::pulse(int duration)
- If the emitter is not enabled, enables it for duration milliseconds and then switches
- it back off.
+ If the emitter is not enabled, enables it for a specified \a duration
+ (in milliseconds) and then switches it back off.
*/
QQuickParticleEmitter::QQuickParticleEmitter(QQuickItem *parent) :
diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h
index 64b9bcef32..b97d3f812a 100644
--- a/src/particles/qquickparticleemitter_p.h
+++ b/src/particles/qquickparticleemitter_p.h
@@ -83,6 +83,7 @@ class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleEmitter : public QQuickItem
Q_PROPERTY(QQuickDirection *velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
Q_PROPERTY(qreal velocityFromMovement READ velocityFromMovement WRITE setVelocityFromMovement NOTIFY velocityFromMovementChanged)
+ QML_NAMED_ELEMENT(Emitter)
public:
explicit QQuickParticleEmitter(QQuickItem *parent = 0);
diff --git a/src/particles/qquickparticleextruder_p.h b/src/particles/qquickparticleextruder_p.h
index 38b2e34c77..24f7a0a2fa 100644
--- a/src/particles/qquickparticleextruder_p.h
+++ b/src/particles/qquickparticleextruder_p.h
@@ -54,6 +54,7 @@
#include <QObject>
#include <QRectF>
#include <QPointF>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +62,9 @@ class QQuickParticleExtruder : public QObject
{
Q_OBJECT
+ QML_NAMED_ELEMENT(ParticleExtruder)
+ QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.")
+
public:
explicit QQuickParticleExtruder(QObject *parent = 0);
virtual QPointF extrude(const QRectF &);
diff --git a/src/particles/qquickparticlegroup_p.h b/src/particles/qquickparticlegroup_p.h
index 0314234569..8d068fbe9c 100644
--- a/src/particles/qquickparticlegroup_p.h
+++ b/src/particles/qquickparticlegroup_p.h
@@ -66,6 +66,7 @@ class QQuickParticleGroup : public QQuickStochasticState, public QQmlParserStatu
//Intercept children requests and assign to the group & system
Q_PROPERTY(QQmlListProperty<QObject> particleChildren READ particleChildren DESIGNABLE false)//### Hidden property for in-state system definitions - ought not to be used in actual "Sprite" states
Q_CLASSINFO("DefaultProperty", "particleChildren")
+ QML_NAMED_ELEMENT(ParticleGroup)
Q_INTERFACES(QQmlParserStatus)
public:
diff --git a/src/particles/qquickparticlepainter_p.h b/src/particles/qquickparticlepainter_p.h
index 16fc6b6f45..e3d13b8a21 100644
--- a/src/particles/qquickparticlepainter_p.h
+++ b/src/particles/qquickparticlepainter_p.h
@@ -64,6 +64,9 @@ class QQuickParticlePainter : public QQuickItem
Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
+ QML_NAMED_ELEMENT(ParticlePainter)
+ QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.")
+
public: // data
typedef QQuickParticleVarLengthArray<QQuickParticleGroupData::ID, 4> GroupIDs;
diff --git a/src/particles/qquickparticlesmodule.cpp b/src/particles/qquickparticlesmodule.cpp
index 03f47a3961..4f2e1cf29d 100644
--- a/src/particles/qquickparticlesmodule.cpp
+++ b/src/particles/qquickparticlesmodule.cpp
@@ -84,47 +84,45 @@ void QQuickParticlesModule::defineModule()
const char* uri = "QtQuick.Particles";
- qmlRegisterType<QQuickParticleSystem>(uri, 2, 0, "ParticleSystem");
- qmlRegisterType<QQuickParticleGroup>(uri, 2, 0, "ParticleGroup");
+ qmlRegisterTypesAndRevisions<
+ QQuickParticleSystem,
+ QQuickParticleGroup,
- qmlRegisterType<QQuickImageParticle>(uri, 2, 0, "ImageParticle");
+ QQuickImageParticle,
#if QT_CONFIG(quick_shadereffect)
- qmlRegisterType<QQuickCustomParticle>(uri, 2, 0, "CustomParticle");
+ QQuickCustomParticle,
#endif
- qmlRegisterType<QQuickItemParticle>(uri, 2, 0, "ItemParticle");
+ QQuickItemParticle,
- qmlRegisterType<QQuickParticleEmitter>(uri, 2, 0, "Emitter");
- qmlRegisterType<QQuickTrailEmitter>(uri, 2, 0, "TrailEmitter");
+ QQuickParticleEmitter,
+ QQuickTrailEmitter,
- qmlRegisterType<QQuickEllipseExtruder>(uri, 2, 0, "EllipseShape");
- qmlRegisterType<QQuickRectangleExtruder>(uri, 2, 0, "RectangleShape");
- qmlRegisterType<QQuickLineExtruder>(uri, 2, 0, "LineShape");
- qmlRegisterType<QQuickMaskExtruder>(uri, 2, 0, "MaskShape");
+ QQuickEllipseExtruder,
+ QQuickRectangleExtruder,
+ QQuickLineExtruder,
+ QQuickMaskExtruder,
- qmlRegisterType<QQuickPointDirection>(uri, 2, 0, "PointDirection");
- qmlRegisterType<QQuickAngleDirection>(uri, 2, 0, "AngleDirection");
- qmlRegisterType<QQuickTargetDirection>(uri, 2, 0, "TargetDirection");
- qmlRegisterType<QQuickCumulativeDirection>(uri, 2, 0, "CumulativeDirection");
+ QQuickPointDirection,
+ QQuickAngleDirection,
+ QQuickTargetDirection,
+ QQuickCumulativeDirection,
- qmlRegisterType<QQuickCustomAffector>(uri, 2, 0, "Affector");
- qmlRegisterType<QQuickWanderAffector>(uri, 2, 0, "Wander");
- qmlRegisterType<QQuickFrictionAffector>(uri, 2, 0, "Friction");
- qmlRegisterType<QQuickAttractorAffector>(uri, 2, 0, "Attractor");
- qmlRegisterType<QQuickGravityAffector>(uri, 2, 0, "Gravity");
- qmlRegisterType<QQuickAgeAffector>(uri, 2, 0, "Age");
- qmlRegisterType<QQuickSpriteGoalAffector>(uri, 2, 0, "SpriteGoal");
- qmlRegisterType<QQuickGroupGoalAffector>(uri, 2, 0, "GroupGoal");
- qmlRegisterType<QQuickTurbulenceAffector>(uri, 2, 0 , "Turbulence");
+ QQuickCustomAffector,
+ QQuickWanderAffector,
+ QQuickFrictionAffector,
+ QQuickAttractorAffector,
+ QQuickGravityAffector,
+ QQuickAgeAffector,
+ QQuickSpriteGoalAffector,
+ QQuickGroupGoalAffector,
+ QQuickTurbulenceAffector,
- //Exposed just for completeness
- qmlRegisterUncreatableType<QQuickParticleAffector>(uri, 2, 0, "ParticleAffector",
- QStringLiteral("Abstract type. Use one of the inheriting types instead."));
- qmlRegisterUncreatableType<QQuickParticlePainter>(uri, 2, 0, "ParticlePainter",
- QStringLiteral("Abstract type. Use one of the inheriting types instead."));
- qmlRegisterUncreatableType<QQuickParticleExtruder>(uri, 2, 0, "ParticleExtruder",
- QStringLiteral("Abstract type. Use one of the inheriting types instead."));
- qmlRegisterUncreatableType<QQuickDirection>(uri, 2, 0, "NullVector",
- QStringLiteral("Abstract type. Use one of the inheriting types instead."));
+ // Exposed just for completeness
+ QQuickParticleAffector,
+ QQuickParticlePainter,
+ QQuickParticleExtruder,
+ QQuickDirection
+ >(uri, 2);
}
QT_END_NAMESPACE
diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h
index 1e34086b0c..dd721a7164 100644
--- a/src/particles/qquickparticlesystem_p.h
+++ b/src/particles/qquickparticlesystem_p.h
@@ -349,6 +349,7 @@ class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleSystem : public QQuickItem
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
+ QML_NAMED_ELEMENT(ParticleSystem)
public:
explicit QQuickParticleSystem(QQuickItem *parent = nullptr);
diff --git a/src/particles/qquickpointattractor_p.h b/src/particles/qquickpointattractor_p.h
index 47985b5e82..28bbaaa84f 100644
--- a/src/particles/qquickpointattractor_p.h
+++ b/src/particles/qquickpointattractor_p.h
@@ -62,6 +62,7 @@ class QQuickAttractorAffector : public QQuickParticleAffector
Q_PROPERTY(qreal pointY READ pointY WRITE setPointY NOTIFY pointYChanged)
Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)
+ QML_NAMED_ELEMENT(Attractor)
public:
enum Proportion{
diff --git a/src/particles/qquickpointdirection_p.h b/src/particles/qquickpointdirection_p.h
index a80be928ad..9103a570c9 100644
--- a/src/particles/qquickpointdirection_p.h
+++ b/src/particles/qquickpointdirection_p.h
@@ -61,6 +61,7 @@ class QQuickPointDirection : public QQuickDirection
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
Q_PROPERTY(qreal xVariation READ xVariation WRITE setXVariation NOTIFY xVariationChanged)
Q_PROPERTY(qreal yVariation READ yVariation WRITE setYVariation NOTIFY yVariationChanged)
+ QML_NAMED_ELEMENT(PointDirection)
public:
explicit QQuickPointDirection(QObject *parent = 0);
QPointF sample(const QPointF &from) override;
diff --git a/src/particles/qquickrectangleextruder_p.h b/src/particles/qquickrectangleextruder_p.h
index 630cf3050d..7c0a6c2bf1 100644
--- a/src/particles/qquickrectangleextruder_p.h
+++ b/src/particles/qquickrectangleextruder_p.h
@@ -59,6 +59,7 @@ class QQuickRectangleExtruder : public QQuickParticleExtruder
{
Q_OBJECT
Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)
+ QML_NAMED_ELEMENT(RectangleShape)
public:
explicit QQuickRectangleExtruder(QObject *parent = 0);
diff --git a/src/particles/qquickspritegoal_p.h b/src/particles/qquickspritegoal_p.h
index e569603550..d5f9bb88ae 100644
--- a/src/particles/qquickspritegoal_p.h
+++ b/src/particles/qquickspritegoal_p.h
@@ -63,6 +63,7 @@ class QQuickSpriteGoalAffector : public QQuickParticleAffector
Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged)
Q_PROPERTY(bool systemStates READ systemStates WRITE setSystemStates NOTIFY systemStatesChanged)
+ QML_NAMED_ELEMENT(SpriteGoal)
public:
explicit QQuickSpriteGoalAffector(QQuickItem *parent = 0);
diff --git a/src/particles/qquicktargetdirection_p.h b/src/particles/qquicktargetdirection_p.h
index 13e826743e..232d375d8c 100644
--- a/src/particles/qquicktargetdirection_p.h
+++ b/src/particles/qquicktargetdirection_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
#include "qquickdirection_p.h"
+#include <QtQml/qqml.h>
+
QT_BEGIN_NAMESPACE
class QQuickItem;
@@ -68,6 +70,7 @@ class QQuickTargetDirection : public QQuickDirection
Q_PROPERTY(bool proportionalMagnitude READ proportionalMagnitude WRITE setProportionalMagnitude NOTIFY proprotionalMagnitudeChanged)
Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
+ QML_NAMED_ELEMENT(TargetDirection)
public:
explicit QQuickTargetDirection(QObject *parent = 0);
diff --git a/src/particles/qquicktrailemitter_p.h b/src/particles/qquicktrailemitter_p.h
index 22b96afd25..270bec52cf 100644
--- a/src/particles/qquicktrailemitter_p.h
+++ b/src/particles/qquicktrailemitter_p.h
@@ -64,6 +64,7 @@ class QQuickTrailEmitter : public QQuickParticleEmitter
Q_PROPERTY(QQuickParticleExtruder* emitShape READ emissonShape WRITE setEmissionShape NOTIFY emissionShapeChanged)
Q_PROPERTY(qreal emitHeight READ emitterYVariation WRITE setEmitterYVariation NOTIFY emitterYVariationChanged)
Q_PROPERTY(qreal emitWidth READ emitterXVariation WRITE setEmitterXVariation NOTIFY emitterXVariationChanged)
+ QML_NAMED_ELEMENT(TrailEmitter)
public:
enum EmitSize {
diff --git a/src/particles/qquickturbulence_p.h b/src/particles/qquickturbulence_p.h
index e73f3ba153..52011381e4 100644
--- a/src/particles/qquickturbulence_p.h
+++ b/src/particles/qquickturbulence_p.h
@@ -62,7 +62,9 @@ class QQuickTurbulenceAffector : public QQuickParticleAffector
Q_OBJECT
Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
Q_PROPERTY(QUrl noiseSource READ noiseSource WRITE setNoiseSource NOTIFY noiseSourceChanged)
- public:
+ QML_NAMED_ELEMENT(Turbulence)
+
+public:
explicit QQuickTurbulenceAffector(QQuickItem *parent = 0);
~QQuickTurbulenceAffector();
void affectSystem(qreal dt) override;
diff --git a/src/particles/qquickwander_p.h b/src/particles/qquickwander_p.h
index 0ad19d4d13..bf7acdacfb 100644
--- a/src/particles/qquickwander_p.h
+++ b/src/particles/qquickwander_p.h
@@ -71,6 +71,7 @@ class QQuickWanderAffector : public QQuickParticleAffector
Q_PROPERTY(qreal xVariance READ xVariance WRITE setXVariance NOTIFY xVarianceChanged)
Q_PROPERTY(qreal yVariance READ yVariance WRITE setYVariance NOTIFY yVarianceChanged)
Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
+ QML_NAMED_ELEMENT(Wander)
public:
enum AffectableParameters {
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index d0f9833c2e..029004ffd1 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -191,22 +191,18 @@ QQmlEngineDebugServiceImpl::propertyData(QObject *obj, int propIdx)
if (binding)
rv.binding = binding->expression();
- if (QQmlValueTypeFactory::isValueType(prop.userType())) {
- rv.type = QQmlObjectProperty::Basic;
- } else if (QQmlMetaType::isQObject(prop.userType())) {
+ rv.value = valueContents(prop.read(obj));
+
+ if (QQmlMetaType::isQObject(prop.userType())) {
rv.type = QQmlObjectProperty::Object;
} else if (QQmlMetaType::isList(prop.userType())) {
rv.type = QQmlObjectProperty::List;
} else if (prop.userType() == QMetaType::QVariant) {
rv.type = QQmlObjectProperty::Variant;
+ } else if (rv.value.isValid()) {
+ rv.type = QQmlObjectProperty::Basic;
}
- QVariant value;
- if (rv.type != QQmlObjectProperty::Unknown && prop.userType() != 0) {
- value = prop.read(obj);
- }
- rv.value = valueContents(value);
-
return rv;
}
@@ -269,10 +265,10 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
return s;
}
}
-
- if (isSaveable(value))
- return value;
}
+
+ if (isSaveable(value))
+ return value;
}
if (QQmlMetaType::isQObject(userType)) {
@@ -494,7 +490,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
QQmlDebugPacket ds(message);
QByteArray type;
- int queryId;
+ qint32 queryId;
ds >> type >> queryId;
QQmlDebugPacket rs;
@@ -507,13 +503,13 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
QJSEngine *engine = m_engines.at(ii);
QString engineName = engine->objectName();
- int engineId = QQmlDebugService::idForObject(engine);
+ qint32 engineId = QQmlDebugService::idForObject(engine);
rs << engineName << engineId;
}
} else if (type == "LIST_OBJECTS") {
- int engineId = -1;
+ qint32 engineId = -1;
ds >> engineId;
QQmlEngine *engine =
@@ -536,7 +532,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
}
} else if (type == "FETCH_OBJECT") {
- int objectId;
+ qint32 objectId;
bool recurse;
bool dumpProperties = true;
@@ -554,8 +550,8 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
} else if (type == "FETCH_OBJECTS_FOR_LOCATION") {
QString file;
- int lineNumber;
- int columnNumber;
+ qint32 lineNumber;
+ qint32 columnNumber;
bool recurse;
bool dumpProperties = true;
@@ -573,7 +569,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
}
} else if (type == "WATCH_OBJECT") {
- int objectId;
+ qint32 objectId;
ds >> objectId;
bool ok = m_watch->addWatch(queryId, objectId);
@@ -581,7 +577,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
} else if (type == "WATCH_PROPERTY") {
- int objectId;
+ qint32 objectId;
QByteArray property;
ds >> objectId >> property;
@@ -590,7 +586,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
} else if (type == "WATCH_EXPR_OBJECT") {
- int debugId;
+ qint32 debugId;
QString expr;
ds >> debugId >> expr;
@@ -604,11 +600,11 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("NO_WATCH_R") << queryId << ok;
} else if (type == "EVAL_EXPRESSION") {
- int objectId;
+ qint32 objectId;
QString expr;
ds >> objectId >> expr;
- int engineId = -1;
+ qint32 engineId = -1;
if (!ds.atEnd())
ds >> engineId;
@@ -636,12 +632,12 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
} else if (type == "SET_BINDING") {
- int objectId;
+ qint32 objectId;
QString propertyName;
QVariant expr;
bool isLiteralValue;
QString filename;
- int line;
+ qint32 line;
ds >> objectId >> propertyName >> expr >> isLiteralValue >>
filename >> line;
bool ok = setBinding(objectId, propertyName, expr, isLiteralValue,
@@ -650,7 +646,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("SET_BINDING_R") << queryId << ok;
} else if (type == "RESET_BINDING") {
- int objectId;
+ qint32 objectId;
QString propertyName;
ds >> objectId >> propertyName;
bool ok = resetBinding(objectId, propertyName);
@@ -658,7 +654,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
rs << QByteArray("RESET_BINDING_R") << queryId << ok;
} else if (type == "SET_METHOD_BODY") {
- int objectId;
+ qint32 objectId;
QString methodName;
QString methodBody;
ds >> objectId >> methodName >> methodBody;
@@ -821,7 +817,8 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
return true;
}
-void QQmlEngineDebugServiceImpl::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
+void QQmlEngineDebugServiceImpl::propertyChanged(
+ qint32 id, qint32 objectId, const QMetaProperty &property, const QVariant &value)
{
QQmlDebugPacket rs;
rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
@@ -852,14 +849,14 @@ void QQmlEngineDebugServiceImpl::objectCreated(QJSEngine *engine, QObject *objec
if (!m_engines.contains(engine))
return;
- int engineId = QQmlDebugService::idForObject(engine);
- int objectId = QQmlDebugService::idForObject(object);
- int parentId = QQmlDebugService::idForObject(object->parent());
+ qint32 engineId = QQmlDebugService::idForObject(engine);
+ qint32 objectId = QQmlDebugService::idForObject(object);
+ qint32 parentId = QQmlDebugService::idForObject(object->parent());
QQmlDebugPacket rs;
//unique queryId -1
- rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId;
+ rs << QByteArray("OBJECT_CREATED") << qint32(-1) << engineId << objectId << parentId;
emit messageToClient(name(), rs.data());
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
index c0c24058eb..741768cd00 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
@@ -111,7 +111,8 @@ private:
friend class QQmlDebuggerServiceFactory;
void processMessage(const QByteArray &msg);
- void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
+ void propertyChanged(qint32 id, qint32 objectId, const QMetaProperty &property,
+ const QVariant &value);
void prepareDeferredObjects(QObject *);
void buildObjectList(QDataStream &, QQmlContext *,
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
index 86571e6cbe..8caa5ac23e 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
@@ -109,12 +109,7 @@ QQmlWatchProxy::QQmlWatchProxy(int id,
void QQmlWatchProxy::notifyValueChanged()
{
- QVariant v;
- if (m_expr)
- v = m_expr->evaluate();
- else if (QQmlValueTypeFactory::isValueType(m_property.userType()))
- v = m_property.read(m_object);
-
+ const QVariant v = m_expr ? m_expr->evaluate() : m_property.read(m_object);
emit m_watch->propertyChanged(m_id, m_debugId, m_property, v);
}
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index 2d5282b48c..cc663cd6b3 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -506,7 +506,7 @@ void QQmlDebugServerImpl::receiveMessage()
in >> m_clientPlugins;
for (DebugServiceConstIt iter = m_plugins.constBegin(), cend = m_plugins.constEnd(); iter != cend; ++iter) {
- const QString pluginName = iter.key();
+ const QString &pluginName = iter.key();
QQmlDebugService::State newState = QQmlDebugService::Unavailable;
if (m_clientPlugins.contains(pluginName))
newState = QQmlDebugService::Enabled;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
index 0d501f48c0..4a6894e69e 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
@@ -148,7 +148,7 @@ void QSGD3D12RenderLoop::windowDestroyed(QQuickWindow *window)
delete rc;
delete engine;
- delete wd->animationController;
+ wd->animationController.reset();
}
void QSGD3D12RenderLoop::exposeWindow(QQuickWindow *window)
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
index f505df1e5a..4302a9119b 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
@@ -373,7 +373,7 @@ bool QSGD3D12RenderThread::event(QEvent *e)
QCoreApplication::processEvents();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
if (wme->destroying)
- delete wd->animationController;
+ wd->animationController.reset();
}
if (wme->destroying)
active = false;
@@ -1006,7 +1006,7 @@ void QSGD3D12ThreadedRenderLoop::handleExposure(QQuickWindow *window)
if (Q_UNLIKELY(debug_loop()))
qDebug("starting render thread");
// Push a few things to the render thread.
- QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController;
+ QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController.data();
if (controller->thread() != w->thread)
controller->moveToThread(w->thread);
if (w->thread->thread() == QThread::currentThread()) {
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp b/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp
index 1736a2098e..a5231e15d1 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp
@@ -76,6 +76,7 @@ void QSGOpenVGRenderContext::initialize(const QSGRenderContext::InitParams *para
m_vgContext = vgparams->context;
QSGRenderContext::initialize(params);
+ emit initialized();
}
void QSGOpenVGRenderContext::invalidate()
@@ -84,6 +85,7 @@ void QSGOpenVGRenderContext::invalidate()
delete m_glyphCacheManager;
m_glyphCacheManager = nullptr;
QSGRenderContext::invalidate();
+ emit invalidated();
}
void QSGOpenVGRenderContext::renderNextFrame(QSGRenderer *renderer, uint fboId)
diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp
index d728686248..2c71c1610a 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp
@@ -211,21 +211,14 @@ void QSGOpenVGInternalRectangleNode::render()
} else {
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
- if (m_radius > 0) {
- // Fallback to rendering to an image for rounded rects with perspective transforms
- if (m_offscreenSurface == nullptr || m_offscreenSurface->size() != QSize(std::ceil(m_rect.width()), std::ceil(m_rect.height()))) {
- delete m_offscreenSurface;
- m_offscreenSurface = new QOpenVGOffscreenSurface(QSize(std::ceil(m_rect.width()), std::ceil(m_rect.height())));
- }
-
- m_offscreenSurface->makeCurrent();
- } else if (m_offscreenSurface) {
+ // Fallback to rendering to an image for rounded rects with perspective transforms
+ if (m_offscreenSurface == nullptr || m_offscreenSurface->size() != QSize(std::ceil(m_rect.width()), std::ceil(m_rect.height()))) {
delete m_offscreenSurface;
- m_offscreenSurface = nullptr;
+ m_offscreenSurface = new QOpenVGOffscreenSurface(QSize(std::ceil(m_rect.width()), std::ceil(m_rect.height())));
}
+ m_offscreenSurface->makeCurrent();
}
-
// If path is dirty
if (m_pathDirty) {
vgClearPath(m_rectanglePath, VG_PATH_CAPABILITY_APPEND_TO);
@@ -291,7 +284,7 @@ void QSGOpenVGInternalRectangleNode::render()
vgDrawPath(m_rectanglePath, VG_FILL_PATH);
}
- if (!transform().isAffine() && m_radius > 0) {
+ if (!transform().isAffine()) {
m_offscreenSurface->doneCurrent();
// Render offscreen surface
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp
index 94f7f76036..85651ece9d 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp
@@ -96,7 +96,7 @@ void QSGOpenVGRenderLoop::windowDestroyed(QQuickWindow *window)
vg->doneCurrent();
}
- delete d->animationController;
+ d->animationController.reset();
}
void QSGOpenVGRenderLoop::exposureChanged(QQuickWindow *window)
@@ -187,6 +187,7 @@ void QSGOpenVGRenderLoop::renderWindow(QQuickWindow *window)
data.updatePending = false;
if (!data.grabOnly) {
+ cd->flushFrameSynchronousEvents();
// Event delivery/processing triggered the window to be deleted or stop rendering.
if (!m_windows.contains(window))
return;
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp
index fb24df7471..1b75d450aa 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp
@@ -52,7 +52,7 @@ QSGOpenVGSpriteNode::QSGOpenVGSpriteNode()
QSGOpenVGSpriteNode::~QSGOpenVGSpriteNode()
{
-
+ delete m_texture;
}
void QSGOpenVGSpriteNode::setTexture(QSGTexture *texture)
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgspritenode.h b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.h
index d47b389a0b..dba4e663be 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgspritenode.h
+++ b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.h
@@ -66,7 +66,7 @@ public:
void render() override;
private:
- QSGOpenVGTexture *m_texture;
+ QSGOpenVGTexture *m_texture = nullptr;
float m_time;
QPoint m_sourceA;
QPoint m_sourceB;
diff --git a/src/qml/common/qqmlapiversion_p.h b/src/qml/common/qqmlapiversion_p.h
index eca05558d8..576619c518 100644
--- a/src/qml/common/qqmlapiversion_p.h
+++ b/src/qml/common/qqmlapiversion_p.h
@@ -51,6 +51,6 @@
// We mean it.
//
-#define Q_QML_PRIVATE_API_VERSION 5
+#define Q_QML_PRIVATE_API_VERSION 6
#endif // QQMLAPIVERSION_P_H
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index c3ddce5884..11de506a53 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE
// Also change the comment behind the number to describe the latest change. This has the added
// benefit that if another patch changes the version too, it will result in a merge conflict, and
// not get removed silently.
-#define QV4_DATA_STRUCTURE_VERSION 0x24 // Collect function parameter types
+#define QV4_DATA_STRUCTURE_VERSION 0x26// support required properties
class QIODevice;
class QQmlTypeNameCache;
@@ -656,7 +656,8 @@ struct Property
{
quint32_le nameIndex;
union {
- quint32_le_bitfield<0, 29> builtinTypeOrTypeNameIndex;
+ quint32_le_bitfield<0, 28> builtinTypeOrTypeNameIndex;
+ quint32_le_bitfield<28, 1> isRequired;
quint32_le_bitfield<29, 1> isBuiltinType;
quint32_le_bitfield<30, 1> isList;
quint32_le_bitfield<31, 1> isReadOnly;
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 171dc641d3..940d61ba97 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -792,7 +792,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
{
if (node->type == QQmlJS::AST::UiPublicMember::Signal) {
Signal *signal = New<Signal>();
- QString signalName = node->name.toString();
+ const QString signalName = node->name.toString();
signal->nameIndex = registerString(signalName);
QQmlJS::AST::SourceLocation loc = node->typeToken;
@@ -821,8 +821,14 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
p = p->next;
}
- if (signalName.at(0).isUpper())
- COMPILE_EXCEPTION(node->identifierToken, tr("Signal names cannot begin with an upper case letter"));
+ for (const QChar &ch : signalName) {
+ if (ch.isLower())
+ break;
+ if (ch.isUpper()) {
+ COMPILE_EXCEPTION(node->identifierToken,
+ tr("Signal names cannot begin with an upper case letter"));
+ }
+ }
if (illegalNames.contains(signalName))
COMPILE_EXCEPTION(node->identifierToken, tr("Illegal signal name"));
@@ -841,6 +847,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
Property *property = New<Property>();
property->isReadOnly = node->isReadonlyMember;
+ property->isRequired = node->isRequired;
QV4::CompiledData::BuiltinType builtinPropertyType = Parameter::stringToBuiltinType(memberType);
bool typeFound = builtinPropertyType != QV4::CompiledData::BuiltinType::InvalidBuiltin;
@@ -964,7 +971,7 @@ QStringRef IRBuilder::asStringRef(QQmlJS::AST::Node *node)
return textRefAt(node->firstSourceLocation(), node->lastSourceLocation());
}
-void IRBuilder::extractVersion(QStringRef string, int *maj, int *min)
+void IRBuilder::extractVersion(const QStringRef &string, int *maj, int *min)
{
*maj = -1; *min = -1;
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index c366c8e459..4279f5b768 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -453,7 +453,7 @@ public:
static QString asString(QQmlJS::AST::UiQualifiedId *node);
QStringRef asStringRef(QQmlJS::AST::Node *node);
- static void extractVersion(QStringRef string, int *maj, int *min);
+ static void extractVersion(const QStringRef &string, int *maj, int *min);
QStringRef textRefAt(const QQmlJS::AST::SourceLocation &loc) const
{ return QStringRef(&sourceCode, loc.offset, loc.length); }
QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first,
diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf
index cb9fb575b2..74d0a3b27c 100644
--- a/src/qml/doc/qtqml.qdocconf
+++ b/src/qml/doc/qtqml.qdocconf
@@ -37,11 +37,17 @@ tagfile = ../../../doc/qtqml/qtqml.tags
depends += qtcore qtgui qtquick qtdoc qtlinguist qmake qtscript qtwidgets qtxmlpatterns qtquickcontrols
headerdirs += .. \
- ../../imports/models
+ ../../imports/models \
+ ../../qmlmodels \
+ ../../qml \
+ ../../qmlworkerscript
sourcedirs += .. \
../../imports/models \
- ../../imports/statemachine
+ ../../imports/statemachine \
+ ../../qmlmodels \
+ ../../qml \
+ ../../qmlworkerscript
exampledirs += ../../../examples/qml \
../ \
diff --git a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
index 26556644d6..43987354ae 100644
--- a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
+++ b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
@@ -407,8 +407,7 @@ located at the same level as the application that uses our new import module.
This way, the QML engine will find our module as the default search path for QML
imports includes the directory of the application executable. On \macos, the
plugin binary is copied to \c Contents/PlugIns in the the application bundle;
-this path is set in \l {tutorials/extending-qml/chapter6-plugins/app.pro}
-{chapter6-plugins/app.pro}:
+this path is set in \c {chapter6-plugins/app.pro}:
\quotefromfile tutorials/extending-qml/chapter6-plugins/app.pro
\skipto osx
diff --git a/src/qml/doc/src/javascript/finetuning.qdoc b/src/qml/doc/src/javascript/finetuning.qdoc
new file mode 100644
index 0000000000..fcd710db8b
--- /dev/null
+++ b/src/qml/doc/src/javascript/finetuning.qdoc
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+
+\page qtqml-javascript-finetuning.html
+\title Fine-tuning the JavaScript Engine
+\brief Describes the environment variables available, to control how Javascript is run.
+
+Running JavaScript code can be influenced by a few environment variables, particularly:
+
+\table
+ \header
+ \li Environment Variable
+ \li Description
+ \row
+ \li \c{QV4_JIT_CALL_THRESHOLD}
+ \li The JavaScript engine contains a Just-In-Time compiler (JIT). The JIT will compile
+ frequently run JavaScript functions into machine code to run faster. This
+ environment variable determines how often a function needs to be run to be
+ considered for JIT compilation. The default value is 3 times.
+ \row
+ \li \c{QV4_FORCE_INTERPRETER}
+ \li Setting this environment variable disables the JIT and runs all
+ functions through the interpreter, no matter how often they are called.
+ \row
+ \li \c{QV4_JS_MAX_STACK_SIZE}
+ \li The JavaScript engine reserves a special memory area as a stack to run JavaScript.
+ This stack is separate from the C++ stack. Usually this area is 4MB in size. If this
+ environment variable contains a number, the JavaScript engine interprets it as the
+ size of the memory area, in bytes, to be allocated as the JavaScript stack.
+ \row
+ \li \c{QV4_GC_MAX_STACK_SIZE}
+ \li In addition to the regular JavaScript stack, the JavaScript engine keeps another stack
+ for the garbage collector, usually 2MB of memory. If the garbage collector needs to
+ handle an excessive number of objects at the same time, this stack might overrun.
+ If it contains a number, this environment variable is interpreted as the size in bytes
+ of the memory area that will be allocated as the stack for the garbage collector.
+ \row
+ \li \c{QV4_CRASH_ON_STACKOVERFLOW}
+ \li Usually the JavaScript engine tries to catch C++ stack overflows caused by
+ excessively recursive JavaScript code, and generates a non-fatal error condition.
+ There are separate recursion checks for compiling JavaScript and running JavaScript. A
+ stack overflow when compiling JavaScript indicates that the code contains deeply nested
+ objects and functions. A stack overflow at run-time indicates that the code results in
+ a deeply recursive program. The check for this is only indirectly related to the
+ JavaScript stack size mentioned above, as each JavaScript function call consumes stack
+ space on both, the C++ and the JavaScript stack. The code that checks for excessive
+ recursion is necessarily conservative, as the available stack size depends on many
+ factors and can often be customized by the user. With this environment variable set, the
+ JavaScript engine does not check for stack overflows when compiling or running
+ JavaScript and will not generate exceptions for them. Instead, when the stack overflows
+ the program attempts an invalid memory access. This most likely terminates the
+ program. In turn, the program gets to use up all the stack space the operating system
+ can provide.
+ \warning malicious code may be able to evade the termination and access unexpected
+ memory locations this way.
+ \row
+ \li \c{QV4_MAX_CALL_DEPTH}
+ \li Stack overflows when running (as opposed to compiling) JavaScript are prevented by
+ controlling the call depth: the number of nested function invocations. By
+ default, an exception is generated if the call depth exceeds 1234. If it contains a
+ number, this environment variable overrides the maximum call depth. Beware that the
+ recursion limit when compiling JavaScript is not affected.
+ \row
+ \li \c{QV4_MM_AGGRESSIVE_GC}
+ \li Setting this environment variable runs the garbage collector before each memory
+ allocation. This is very expensive at run-time, but it quickly uncovers many memory
+ management errors, for example the manual deletion of an object belonging to the QML
+ engine from C++.
+ \row
+ \li \c{QV4_PROFILE_WRITE_PERF_MAP}
+ \li On Linux, the \c perf utility can be used to profile programs. To analyze JIT-compiled
+ JavaScript functions, it needs to know about their names and locations in memory. To
+ provide this information, there's a convention to create a special file called
+ \c{perf-<pid>.map} in \e{/tmp} which perf then reads. This environment variable, if
+ set, causes the JIT to generate this file.
+\endtable
+
+*/
+
diff --git a/src/qml/doc/src/javascript/imports.qdoc b/src/qml/doc/src/javascript/imports.qdoc
index 974f2e154f..8e26c4aadd 100644
--- a/src/qml/doc/src/javascript/imports.qdoc
+++ b/src/qml/doc/src/javascript/imports.qdoc
@@ -144,14 +144,17 @@ A JavaScript resource may import a QML module in the following fashion:
.import TypeNamespace MajorVersion.MinorVersion as Qualifier
\endcode
-For example:
+Below you can see an example that also shows how to use the QML types from a
+module imported in javascript:
+
\code
.import Qt.test 1.0 as JsQtTest
+
+var importedEnumValue = JsQtTest.MyQmlObject.EnumValue3
\endcode
In particular, this may be useful in order to access functionality provided
via a singleton type; see qmlRegisterSingletonType() for more information.
\note The .import syntax doesn't work for scripts used in the \l {WorkerScript}
-
*/
diff --git a/src/qml/doc/src/javascript/qtjavascript.qdoc b/src/qml/doc/src/javascript/qtjavascript.qdoc
index ad93d9d9ac..aa4dce6a37 100644
--- a/src/qml/doc/src/javascript/qtjavascript.qdoc
+++ b/src/qml/doc/src/javascript/qtjavascript.qdoc
@@ -26,13 +26,6 @@
****************************************************************************/
/*!
- \group qtjavascript
- \title Scripting Classes and Overviews
-
- \brief Classes for embedding JavaScript in Qt/C++ applications.
-*/
-
-/*!
\page qtjavascript.html
\title Making Applications Scriptable
\ingroup frameworks-technologies
diff --git a/src/qml/doc/src/javascript/string.qdoc b/src/qml/doc/src/javascript/string.qdoc
index f896af3378..47922ff17a 100644
--- a/src/qml/doc/src/javascript/string.qdoc
+++ b/src/qml/doc/src/javascript/string.qdoc
@@ -39,8 +39,8 @@
/*!
\qmlmethod string String::arg(value)
- Returns a copy of this string with the lowest numbered place marker replaced by value,
- i.e., %1, %2, ..., %99. The following example prints "There are 20 items"
+ Returns a copy of this string with the lowest numbered place marker replaced by \a value,
+ i.e., %1, %2, ..., %99. The following example prints "There are 20 items":
\code
var message = "There are %1 items"
diff --git a/src/qml/doc/src/javascript/topic.qdoc b/src/qml/doc/src/javascript/topic.qdoc
index 0c06e14b4c..05fb1ddfdc 100644
--- a/src/qml/doc/src/javascript/topic.qdoc
+++ b/src/qml/doc/src/javascript/topic.qdoc
@@ -81,4 +81,11 @@ These limitations and extensions are documented in the description of the
\l{qtqml-javascript-hostenvironment.html}{JavaScript Host Environment} provided
by the QML engine.
+\section1 Fine Tuning the JavaScript engine
+
+For specific use cases you may want to override some of the parameters the
+JavaScript engine uses for handling memory and compiling JavaScript. See
+\l{qtqml-javascript-finetuning.html}{Fine Tuning the JavaScript engine} for
+more information on these parameters.
+
*/
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index c71d18418a..b2d322465d 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -276,25 +276,14 @@
/*!
\fn int qmlRegisterAnonymousType(const char *uri, int versionMajor)
- This template function registers the C++ type in the QML system. Instances of this type cannot be created from the QML system.
+ This template function registers the C++ type in the QML system as an anonymous type. The
+ resulting QML type does not have a name. Therefore, instances of this type cannot be created from
+ the QML system. You can, however, access instances of the type when they are exposed as properties
+ of other types.
- Use this function when the type will not be referenced by name. Use \a uri and \a versionMajor to indicate to which module the type belongs.
-
- \sa {Choosing the Correct Integration Method Between C++ and QML}
-*/
-
-/*!
- \fn int qmlRegisterType()
- \relates QQmlEngine
- \overload
-
- This template function registers the C++ type in the QML
- system. Instances of this type cannot be created from the QML
- system.
-
- This function should be used when the type will not be referenced by name.
- Specifically, it has to be used for C++ types that are used as the left-hand
- side of a property binding.
+ Use this function when the type will not be referenced by name, specifically for C++ types that
+ are used on the left-hand side of a property binding. To indicate to which module the type belongs
+ use \a uri and \a versionMajor.
For example, consider the following two classes:
@@ -354,18 +343,29 @@
\code
qmlRegisterType<Foo>("App", 1, 0, "Foo");
- qmlRegisterType<Bar>();
+ qmlRegisterAnonymousType<Bar>("App", 1);
\endcode
As the \c Foo type is instantiated in QML, it must be registered
- with the version of \l qmlRegisterType() that takes an import URI.
+ with the version of \l qmlRegisterType() that takes an element name.
Returns the QML type id.
+ \since 5.14
\sa {Choosing the Correct Integration Method Between C++ and QML}
*/
/*!
+ \fn int qmlRegisterType()
+ \relates QQmlEngine
+ \overload
+ \deprecated
+
+ Do not use this function. For anonymous type registrations, use \l qmlRegisterAnonymousType(),
+ and make sure to provide a URI and a major version.
+*/
+
+/*!
\fn int qmlRegisterInterface(const char *typeName)
\relates QQmlEngine
@@ -458,7 +458,7 @@
*/
/*!
- \fn template<typename T> QObject *qmlAttachedPropertiesObject(const QObject *attachee, bool create = true)
+ \fn template<typename T> QObject *qmlAttachedPropertiesObject(const QObject *attachee, bool create)
\relates QQmlEngine
The form of this template function is:
@@ -628,8 +628,7 @@
*/
/*!
- \fn int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int
- versionMinor, const char *typeName, QObject* cppObject)
+ \fn int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject* cppObject)
\relates QQmlEngine
\since 5.14
diff --git a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
index 0faad43f4f..f7d71030b5 100644
--- a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
+++ b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
@@ -479,10 +479,7 @@ Module {
Enum {
name: "Loops"
- values: {
- "Infinite": -2,
- "OnceOnly": 1
- }
+ values: [ "Infinite", "OnceOnly" ]
}
// Signal and Method work the same way. The inner Parameter
diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h
index b9f71b7bd9..b18d082be6 100644
--- a/src/qml/jit/qv4assemblercommon_p.h
+++ b/src/qml/jit/qv4assemblercommon_p.h
@@ -624,9 +624,9 @@ public:
// and jump out of the exception handler.
loadPtr(exceptionHandlerAddress(), ScratchRegister);
Jump exitFunction = branchPtr(Equal, ScratchRegister, TrustedImmPtr(0));
+ loadUndefined();
jump(ScratchRegister);
exitFunction.link(this);
- loadUndefined();
if (functionExit.isSet())
jump(functionExit);
diff --git a/src/qml/jit/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp
index 5e34087ff5..59de86a85d 100644
--- a/src/qml/jit/qv4baselineassembler.cpp
+++ b/src/qml/jit/qv4baselineassembler.cpp
@@ -1474,6 +1474,12 @@ void BaselineAssembler::saveAccumulatorInFrame()
offsetof(CallData, accumulator)));
}
+void BaselineAssembler::loadAccumulatorFromFrame()
+{
+ pasm()->loadAccumulator(PlatformAssembler::Address(PlatformAssembler::JSStackFrameRegister,
+ offsetof(CallData, accumulator)));
+}
+
static ReturnedValue TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing(CppStackFrame *frame, ExecutionEngine *engine)
{
return Runtime::TailCall::call(frame, engine);
@@ -1600,7 +1606,6 @@ void BaselineAssembler::deadTemporalZoneCheck(int offsetForSavedIP, int variable
{
auto valueIsAliveJump = pasm()->jumpNotEmpty();
storeInstructionPointer(offsetForSavedIP);
- saveAccumulatorInFrame();
prepareCallWithArgCount(2);
passInt32AsArg(variableName, 1);
passEngineAsArg(0);
diff --git a/src/qml/jit/qv4baselineassembler_p.h b/src/qml/jit/qv4baselineassembler_p.h
index 5e5d9d0672..33fd288ac3 100644
--- a/src/qml/jit/qv4baselineassembler_p.h
+++ b/src/qml/jit/qv4baselineassembler_p.h
@@ -155,6 +155,7 @@ public:
void passPointerAsArg(void *ptr, int arg);
void callRuntime(const char *functionName, const void *funcPtr, CallResultDestination dest);
void saveAccumulatorInFrame();
+ void loadAccumulatorFromFrame();
void jsTailCall(int func, int thisObject, int argc, int argv);
// exception/context stuff
diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp
index 906cc30e67..fcaa87290e 100644
--- a/src/qml/jit/qv4baselinejit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -74,6 +74,7 @@ void BaselineJIT::generate()
#define STORE_IP() as->storeInstructionPointer(nextInstructionOffset())
#define STORE_ACC() as->saveAccumulatorInFrame()
+#define LOAD_ACC() as->loadAccumulatorFromFrame()
#define BASELINEJIT_GENERATE_RUNTIME_CALL(function, destination) { \
as->GENERATE_RUNTIME_CALL(function, destination); \
if (Runtime::function::throws) \
@@ -228,6 +229,7 @@ void BaselineJIT::generate_StoreNameSloppy(int name)
as->passInt32AsArg(name, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameSloppy, CallResultDestination::Ignore);
+ LOAD_ACC();
}
void BaselineJIT::generate_StoreNameStrict(int name)
@@ -239,6 +241,7 @@ void BaselineJIT::generate_StoreNameStrict(int name)
as->passInt32AsArg(name, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameStrict, CallResultDestination::Ignore);
+ LOAD_ACC();
}
void BaselineJIT::generate_LoadElement(int base)
@@ -262,6 +265,7 @@ void BaselineJIT::generate_StoreElement(int base, int index)
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreElement, CallResultDestination::Ignore);
+ LOAD_ACC();
}
void BaselineJIT::generate_LoadProperty(int name)
@@ -297,6 +301,7 @@ void BaselineJIT::generate_StoreProperty(int name, int base)
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreProperty, CallResultDestination::Ignore);
+ LOAD_ACC();
}
void BaselineJIT::generate_SetLookup(int index, int base)
@@ -317,7 +322,6 @@ void BaselineJIT::generate_SetLookup(int index, int base)
void BaselineJIT::generate_LoadSuperProperty(int property)
{
STORE_IP();
- STORE_ACC();
as->prepareCallWithArgCount(2);
as->passJSSlotAsArg(property, 1);
as->passEngineAsArg(0);
@@ -333,6 +337,7 @@ void BaselineJIT::generate_StoreSuperProperty(int property)
as->passJSSlotAsArg(property, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreSuperProperty, CallResultDestination::Ignore);
+ LOAD_ACC();
}
void BaselineJIT::generate_Yield()
@@ -562,6 +567,7 @@ void BaselineJIT::generate_PushBlockContext(int index)
as->passInt32AsArg(index, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(PushBlockContext, CallResultDestination::Ignore);
+ as->loadAccumulatorFromFrame();
}
void BaselineJIT::generate_CloneBlockContext()
@@ -570,6 +576,7 @@ void BaselineJIT::generate_CloneBlockContext()
as->prepareCallWithArgCount(1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(CloneBlockContext, CallResultDestination::Ignore);
+ as->loadAccumulatorFromFrame();
}
void BaselineJIT::generate_PushScriptContext(int index)
@@ -579,6 +586,7 @@ void BaselineJIT::generate_PushScriptContext(int index)
as->passInt32AsArg(index, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(PushScriptContext, CallResultDestination::Ignore);
+ as->loadAccumulatorFromFrame();
}
void BaselineJIT::generate_PopScriptContext()
@@ -587,6 +595,7 @@ void BaselineJIT::generate_PopScriptContext()
as->prepareCallWithArgCount(1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(PopScriptContext, CallResultDestination::Ignore);
+ as->loadAccumulatorFromFrame();
}
void BaselineJIT::generate_PopContext() { as->popContext(); }
@@ -682,11 +691,13 @@ void BaselineJIT::generate_TypeofValue()
void BaselineJIT::generate_DeclareVar(int varName, int isDeletable)
{
+ STORE_ACC();
as->prepareCallWithArgCount(3);
as->passInt32AsArg(varName, 2);
as->passInt32AsArg(isDeletable, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(DeclareVar, CallResultDestination::Ignore);
+ LOAD_ACC();
}
void BaselineJIT::generate_DefineArray(int argc, int args)
@@ -744,11 +755,13 @@ void BaselineJIT::generate_CreateRestParameter(int argIndex)
void BaselineJIT::generate_ConvertThisToObject()
{
+ STORE_ACC();
as->prepareCallWithArgCount(2);
as->passJSSlotAsArg(CallData::This, 1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(ConvertThisToObject, CallResultDestination::InAccumulator);
as->storeReg(CallData::This);
+ LOAD_ACC();
}
void BaselineJIT::generate_LoadSuperConstructor()
@@ -893,6 +906,7 @@ void BaselineJIT::generate_ThrowOnNullOrUndefined()
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowOnNullOrUndefined, CallResultDestination::Ignore);
+ LOAD_ACC();
}
void BaselineJIT::generate_GetTemplateObject(int index)
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 1bfd72227f..065fbc1c0a 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -615,7 +615,9 @@ QJSValue QJSEngine::newObject()
/*!
\since 5.12
- Creates a JavaScript object of class Error.
+
+ Creates a JavaScript object of class Error, with \a message as the error
+ message.
The prototype of the created object will be \a errorType.
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index bba88e5c9a..cc89947cec 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -294,13 +294,28 @@ static double MakeDay(double year, double month, double day)
if (month < 0)
month += 12.0;
- double d = DayFromYear(year);
- bool leap = InLeapYear(d*msPerDay);
+ /* Quoting the spec:
- d += DayFromMonth(month, leap);
- d += day - 1;
+ Find a value t such that YearFromTime(t) is ym and MonthFromTime(t) is mn
+ and DateFromTime(t) is 1; but if this is not possible (because some
+ argument is out of range), return NaN.
+ */
+ double first = DayFromYear(year);
+ /* Beware floating-point glitches: don't test the first millisecond of a
+ * year, month or day when we could test a moment firmly in the interior of
+ * the interval. A rounding glitch might give the first millisecond to the
+ * preceding interval.
+ */
+ bool leap = InLeapYear((first + 60) * msPerDay);
- return d;
+ first += DayFromMonth(month, leap);
+ const double t = first * msPerDay + msPerDay / 2; // Noon on the first of the month
+ Q_ASSERT(Day(t) == first);
+ if (YearFromTime(t) != year || MonthFromTime(t) != month || DateFromTime(t) != 1) {
+ qWarning("Apparently out-of-range date %.0f-%02.0f-%02.0f", year, month, day);
+ return qt_qnan();
+ }
+ return first + day - 1;
}
static inline double MakeDate(double day, double time)
@@ -601,8 +616,7 @@ static inline double ParseString(const QString &s, double localTZA)
QStringLiteral("d MMMM, yyyy hh:mm:ss"),
};
- for (uint i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) {
- const QString &format(formats[i]);
+ for (const QString &format : formats) {
dt = format.indexOf(QLatin1String("hh:mm")) < 0
? QDateTime(QDate::fromString(s, format),
QTime(0, 0, 0), Qt::UTC)
@@ -729,14 +743,16 @@ void Heap::DateObject::init(const QTime &time)
* time from it, which shall (via toQDateTime(), below) discard the date
* part. We need a date for which time-zone data is likely to be sane (so
* MakeDay(0, 0, 0) was a bad choice; 2 BC, December 31st is before
- * time-zones were standardized), with no transition nearby in date. We
- * ignore DST transitions before 1970, but even then zone transitions did
- * happen. Some do happen at new year, others on DST transitions in spring
- * and autumn; so pick the three hundredth anniversary of the birth of
- * Giovanni Domenico Cassini (1625-06-08), whose work first let us
- * synchronize clocks tolerably accurately at distant locations.
+ * time-zones were standardized), with no transition nearby in date.
+ * QDateTime ignores DST transitions before 1970, but even then zone
+ * transitions did happen; and DaylightSavingTA() will include DST, at odds
+ * with QDateTime. So pick a date since 1970 and prefer one when no zone
+ * was in DST. One such interval (according to the Olson database, at
+ * least) was 1971 March 15th to April 17th. Since converting a time to a
+ * date-time without specifying a date is foolish, let's use April Fools'
+ * day.
*/
- static const double d = MakeDay(1925, 5, 8);
+ static const double d = MakeDay(1971, 3, 1);
double t = MakeTime(time.hour(), time.minute(), time.second(), time.msec());
date = TimeClip(UTC(MakeDate(d, t), internalClass->engine->localTZA));
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index be0de09d79..590cebfa7c 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -216,15 +216,19 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
memoryManager = new QV4::MemoryManager(this);
if (maxCallDepth == -1) {
- ok = false;
- maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
- if (!ok || maxCallDepth <= 0) {
+ if (qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW")) {
+ maxCallDepth = std::numeric_limits<qint32>::max();
+ } else {
+ ok = false;
+ maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
+ if (!ok || maxCallDepth <= 0) {
#if defined(QT_NO_DEBUG) && !defined(__SANITIZE_ADDRESS__) && !QT_HAS_FEATURE(address_sanitizer)
- maxCallDepth = 1234;
+ maxCallDepth = 1234;
#else
- // no (tail call) optimization is done, so there'll be a lot mare stack frames active
- maxCallDepth = 200;
+ // no (tail call) optimization is done, so there'll be a lot mare stack frames active
+ maxCallDepth = 200;
#endif
+ }
}
}
Q_ASSERT(maxCallDepth > 0);
@@ -1761,6 +1765,12 @@ ReturnedValue ExecutionEngine::global()
QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(const QUrl &url)
{
+ QQmlMetaType::CachedUnitLookupError cacheError = QQmlMetaType::CachedUnitLookupError::NoError;
+ if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url, &cacheError)) {
+ return ExecutableCompilationUnit::create(
+ QV4::CompiledData::CompilationUnit(cachedUnit, url.fileName(), url.toString()));
+ }
+
QFile f(QQmlFile::urlToLocalFileOrQrc(url));
if (!f.open(QIODevice::ReadOnly)) {
throwError(QStringLiteral("Could not open module %1 for reading").arg(url.toString()));
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 950e0b10ea..d51e986006 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -52,6 +52,7 @@
#include <private/qv4module_p.h>
#include <private/qv4compilationunitmapper_p.h>
#include <private/qml_compile_hash_p.h>
+#include <private/qqmltypewrapper_p.h>
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlpropertymap.h>
@@ -291,15 +292,18 @@ void ExecutableCompilationUnit::unlink()
if (runtimeLookups) {
for (uint i = 0; i < data->lookupTableSize; ++i) {
QV4::Lookup &l = runtimeLookups[i];
- if (l.getter == QV4::QObjectWrapper::lookupGetter) {
+ if (l.getter == QV4::QObjectWrapper::lookupGetter
+ || l.getter == QQmlTypeWrapper::lookupSingletonProperty) {
if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
pc->release();
- } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) {
+ } else if (l.getter == QQmlValueTypeWrapper::lookupGetter
+ || l.getter == QQmlTypeWrapper::lookupSingletonProperty) {
if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache)
pc->release();
}
- if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) {
+ if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty
+ || l.qmlContextPropertyGetter == QQmlContextWrapper::lookupContextObjectProperty) {
if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
pc->release();
}
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 7578de4d14..31c90b31f6 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -151,6 +151,19 @@ struct Q_QML_PRIVATE_EXPORT Lookup {
quintptr reserved3;
ReturnedValue (*getterTrampoline)(Lookup *l, ExecutionEngine *engine);
} qmlContextGlobalLookup;
+ struct {
+ Heap::Object *qmlTypeWrapper;
+ quintptr unused2;
+ } qmlTypeLookup;
+ struct {
+ Heap::InternalClass *ic;
+ quintptr unused;
+ ReturnedValue encodedEnumValue;
+ } qmlEnumValueLookup;
+ struct {
+ Heap::InternalClass *ic;
+ Heap::Object *qmlScopedEnumWrapper;
+ } qmlScopedEnumWrapperLookup;
};
uint nameIndex;
diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp
index 27075e96a0..17d218a6eb 100644
--- a/src/qml/jsruntime/qv4promiseobject.cpp
+++ b/src/qml/jsruntime/qv4promiseobject.cpp
@@ -163,6 +163,7 @@ void ReactionHandler::executeReaction(ReactionEvent *event)
ScopedFunctionObject reaction(scope);
if (scope.hasException()) {
reaction = capability->d()->reject.as<QV4::FunctionObject>();
+ result = scope.engine->catchException();
} else {
reaction = capability->d()->resolve.as<QV4::FunctionObject>();
}
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index c832bff051..e2d3b98ff6 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -248,11 +248,15 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
return lookup->qmlContextPropertyGetter(lookup, v4, base);
}
}
- return QQmlTypeWrapper::create(v4, scopeObject, r.type);
+ result = QQmlTypeWrapper::create(v4, scopeObject, r.type);
} else if (r.importNamespace) {
- return QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
+ result = QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
}
- Q_ASSERT(!"Unreachable");
+ if (lookup) {
+ lookup->qmlTypeLookup.qmlTypeWrapper = static_cast<Heap::Object*>(result->heapObject());
+ lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupType;
+ }
+ return result->asReturnedValue();
}
// Fall through
@@ -659,6 +663,27 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec
return Encode::undefined();
}
+ReturnedValue QQmlContextWrapper::lookupType(Lookup *l, ExecutionEngine *engine, Value *base)
+{
+ Scope scope(engine);
+ Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
+ if (!qmlContext)
+ return QV4::Encode::undefined();
+
+ QObject *scopeObject = qmlContext->qmlScope();
+ if (scopeObject && QQmlData::wasDeleted(scopeObject))
+ return QV4::Encode::undefined();
+
+ Heap::Object *heapObject = l->qmlTypeLookup.qmlTypeWrapper;
+ if (static_cast<Heap::QQmlTypeWrapper *>(heapObject)->object != scopeObject) {
+ l->qmlTypeLookup.qmlTypeWrapper = nullptr;
+ l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
+ return QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(l, engine, base);
+ }
+
+ return Value::fromHeapObject(heapObject).asReturnedValue();
+}
+
void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml)
{
Heap::ExecutionContext::init(Heap::ExecutionContext::Type_QmlContext);
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index 4c8287ef2f..e3e7239fe5 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -112,6 +112,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
static ReturnedValue lookupContextObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupInParentContextHierarchy(Lookup *l, ExecutionEngine *engine, Value *base);
+ static ReturnedValue lookupType(Lookup *l, ExecutionEngine *engine, Value *base);
};
struct Q_QML_EXPORT QmlContext : public ExecutionContext
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index c36da3815d..2b5e8bd2b9 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -2077,7 +2077,7 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value *
if (!d()->valueTypeWrapper)
return Encode::undefined();
- object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr);
+ object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr());
}
QQmlPropertyData method;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 8a7cbdfb2a..aaa198c62a 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -2050,7 +2050,7 @@ ReturnedValue Runtime::Exp::call(const Value &base, const Value &exp)
double b = base.toNumber();
double e = exp.toNumber();
if (qt_is_inf(e) && (b == 1 || b == -1))
- return Encode(qt_snan());
+ return Encode(qt_qnan());
return Encode(pow(b,e));
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index b4c34d60fa..27d518f5c6 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -647,7 +647,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(LoadSuperProperty)
STORE_IP();
- STORE_ACC();
acc = Runtime::LoadSuperProperty::call(engine, STACK_VALUE(property));
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadSuperProperty)
@@ -794,12 +793,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(Construct)
STORE_IP();
+ STORE_ACC();
acc = Runtime::Construct::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(Construct)
MOTH_BEGIN_INSTR(ConstructWithSpread)
STORE_IP();
+ STORE_ACC();
acc = Runtime::ConstructWithSpread::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(ConstructWithSpread)
@@ -827,7 +828,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(DeadTemporalZoneCheck)
if (ACC.isEmpty()) {
STORE_IP();
- STORE_ACC();
Runtime::ThrowReferenceError::call(engine, name);
goto handleUnwind;
}
@@ -970,6 +970,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(CreateRestParameter)
MOTH_BEGIN_INSTR(ConvertThisToObject)
+ STORE_ACC();
stack[CallData::This] = Runtime::ConvertThisToObject::call(engine, stack[CallData::This]);
CHECK_EXCEPTION;
MOTH_END_INSTR(ConvertThisToObject)
@@ -980,6 +981,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(LoadSuperConstructor)
MOTH_BEGIN_INSTR(ToObject)
+ STORE_ACC();
acc = ACC.toObject(engine)->asReturnedValue();
CHECK_EXCEPTION;
MOTH_END_INSTR(ToObject)
@@ -1247,7 +1249,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
double base = left.toNumber();
double exp = ACC.toNumber();
if (qIsInf(exp) && (base == 1 || base == -1))
- acc = Encode(qSNaN());
+ acc = Encode(qQNaN());
else
acc = Encode(pow(base,exp));
MOTH_END_INSTR(Exp)
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 8ac7633ae0..e28899883f 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -49,6 +49,7 @@
%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
+%token T_FUNCTION_STAR "function *"
%token T_FUNCTION "function" T_GE ">=" T_GT ">"
%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
@@ -88,6 +89,7 @@
%token T_STATIC "static"
%token T_EXPORT "export"
%token T_FROM "from"
+%token T_REQUIRED "required"
--- template strings
%token T_NO_SUBSTITUTION_TEMPLATE"(no subst template)"
@@ -120,8 +122,9 @@
%token T_FOR_LOOKAHEAD_OK "(for lookahead ok)"
--%left T_PLUS T_MINUS
-%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET T_OF T_STATIC T_FROM T_AS
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET T_OF T_STATIC T_FROM T_AS T_REQUIRED
%nonassoc REDUCE_HERE
+%right T_THEN T_ELSE
%start TopLevel
@@ -848,13 +851,7 @@ UiVersionSpecifier: T_VERSION_NUMBER;
UiImport: UiImportHead UiVersionSpecifier Semicolon;
/.
case $rule_number: {
- auto versionToken = loc(2);
- auto version = sym(2).UiVersionSpecifier;
- sym(1).UiImport->version = version;
- if (version->minorToken.isValid()) {
- versionToken.length += version->minorToken.length + (version->minorToken.offset - versionToken.offset - versionToken.length);
- }
- sym(1).UiImport->versionToken = versionToken;
+ sym(1).UiImport->version = sym(2).UiVersionSpecifier;
sym(1).UiImport->semicolonToken = loc(3);
} break;
./
@@ -862,7 +859,6 @@ UiImport: UiImportHead UiVersionSpecifier Semicolon;
UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier Semicolon;
/.
case $rule_number: {
- sym(1).UiImport->versionToken = loc(2);
sym(1).UiImport->version = sym(2).UiVersionSpecifier;
sym(1).UiImport->asToken = loc(3);
sym(1).UiImport->importIdToken = loc(4);
@@ -1175,7 +1171,7 @@ UiObjectMember: T_SIGNAL T_IDENTIFIER Semicolon;
} break;
./
-UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
+UiObjectMemberListPropertyNoInitialiser: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
@@ -1189,23 +1185,19 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier S
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
+UiObjectMember: UiObjectMemberListPropertyNoInitialiser;
+
+UiObjectMember: T_READONLY UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(3);
- node->typeToken = loc(5);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
+UiObjectMemberPropertyNoInitialiser: T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
@@ -1217,42 +1209,47 @@ UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
} break;
./
-UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier Semicolon;
+
+UiObjectMember: UiObjectMemberPropertyNoInitialiser;
+
+UiObjectMember: T_DEFAULT UiObjectMemberPropertyNoInitialiser;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon;
+UiObjectMember: T_DEFAULT UiObjectMemberListPropertyNoInitialiser;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8);
sym(1).Node = node;
} break;
./
+
OptionalSemicolon: | Semicolon;
/.
/* we need OptionalSemicolon because UiScriptStatement might already parse the last semicolon
and then we would miss a semicolon (see tests/auto/quick/qquickvisualdatamodel/data/objectlist.qml)*/
./
-UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
+UiObjectMember: T_REQUIRED UiObjectMemberPropertyNoInitialiser;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
+ node->requiredToken = loc(1);
+ node->isRequired = true;
+ sym(1).Node = node;
+ } break;
+./
+
+
+UiObjectMemberWithScriptStatement: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3), sym(5).Statement);
@@ -1264,35 +1261,29 @@ UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatemen
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
+UiObjectMember: UiObjectMemberWithScriptStatement;
+
+UiObjectMember: T_READONLY UiObjectMemberWithScriptStatement;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement);
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
+UiObjectMember: T_DEFAULT UiObjectMemberWithScriptStatement;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement);
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
sym(1).Node = node;
} break;
./
-UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET Semicolon;
+UiObjectMemberWithArray: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
@@ -1318,35 +1309,19 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET Semicolon;
+UiObjectMember: UiObjectMemberWithArray;
+
+UiObjectMember: T_READONLY UiObjectMemberWithArray;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(3);
- node->typeToken = loc(5);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(7));
- propertyName->identifierToken = loc(7);
- propertyName->next = 0;
-
- AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding(propertyName, sym(10).UiArrayMemberList->finish());
- binding->colonToken = loc(8);
- binding->lbracketToken = loc(9);
- binding->rbracketToken = loc(11);
-
- node->binding = binding;
-
sym(1).Node = node;
} break;
./
-UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer Semicolon;
+UiObjectMemberExpressionStatementLookahead: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer Semicolon;
/.
case $rule_number: {
AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
@@ -1369,43 +1344,30 @@ UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatem
} break;
./
-UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer Semicolon;
+UiObjectMember: UiObjectMemberExpressionStatementLookahead;
+
+UiObjectMember: T_READONLY UiObjectMemberExpressionStatementLookahead;
/.
case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
+ AST::UiPublicMember *node = sym(2).UiPublicMember;
node->isReadonlyMember = true;
node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4));
- propertyName->identifierToken = loc(4);
- propertyName->next = 0;
-
- AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
- propertyName, sym(7).UiQualifiedId, sym(8).UiObjectInitializer);
- binding->colonToken = loc(5);
-
- node->binding = binding;
-
sym(1).Node = node;
} break;
./
-UiObjectMember: FunctionDeclarationWithTypes;
+UiObjectMember: GeneratorDeclaration;
/.
case $rule_number: {
- sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
+ auto node = new (pool) AST::UiSourceElement(sym(1).Node);
+ sym(1).Node = node;
} break;
./
-UiObjectMember: GeneratorExpression;
+UiObjectMember: FunctionDeclarationWithTypes;
/.
case $rule_number: {
- auto node = new (pool) AST::UiSourceElement(sym(1).Node);
- sym(1).Node = node;
+ sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
} break;
./
@@ -1501,6 +1463,7 @@ QmlIdentifier: T_GET;
QmlIdentifier: T_SET;
QmlIdentifier: T_FROM;
QmlIdentifier: T_OF;
+QmlIdentifier: T_REQUIRED;
JsIdentifier: T_IDENTIFIER;
JsIdentifier: T_PROPERTY;
@@ -1513,6 +1476,7 @@ JsIdentifier: T_FROM;
JsIdentifier: T_STATIC;
JsIdentifier: T_OF;
JsIdentifier: T_AS;
+JsIdentifier: T_REQUIRED;
IdentifierReference: JsIdentifier;
BindingIdentifier: IdentifierReference;
@@ -3232,7 +3196,7 @@ ExpressionStatementLookahead: ;
int token = lookaheadToken(lexer);
if (token == T_LBRACE)
pushToken(T_FORCE_BLOCK);
- else if (token == T_FUNCTION || token == T_CLASS || token == T_LET || token == T_CONST)
+ else if (token == T_FUNCTION || token == T_FUNCTION_STAR || token == T_CLASS || token == T_LET || token == T_CONST)
pushToken(T_FORCE_DECLARATION);
} break;
./
@@ -3980,27 +3944,14 @@ GeneratorRBrace: T_RBRACE;
} break;
./
-GeneratorDeclaration: Function T_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
-/.
- case $rule_number: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(3), sym(5).FormalParameterList, sym(8).StatementList);
- node->functionToken = loc(1);
- node->identifierToken = loc(3);
- node->lparenToken = loc(4);
- node->rparenToken = loc(6);
- node->lbraceToken = loc(7);
- node->rbraceToken = loc(9);
- node->isGenerator = true;
- sym(1).Node = node;
- } break;
-./
+FunctionStar: T_FUNCTION_STAR %prec REDUCE_HERE;
-GeneratorDeclaration_Default: GeneratorDeclaration;
-GeneratorDeclaration_Default: Function T_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+GeneratorDeclaration: FunctionStar BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(4).FormalParameterList, sym(7).StatementList);
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
node->functionToken = loc(1);
+ node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
node->lbraceToken = loc(6);
@@ -4010,27 +3961,28 @@ GeneratorDeclaration_Default: Function T_STAR GeneratorLParen FormalParameters T
} break;
./
-GeneratorExpression: T_FUNCTION T_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+GeneratorDeclaration_Default: GeneratorDeclaration;
+GeneratorDeclaration_Default: FunctionStar GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(3), sym(5).FormalParameterList, sym(8).StatementList);
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
node->functionToken = loc(1);
- if (!stringRef(3).isNull())
- node->identifierToken = loc(3);
- node->lparenToken = loc(4);
- node->rparenToken = loc(6);
- node->lbraceToken = loc(7);
- node->rbraceToken = loc(9);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->lbraceToken = loc(5);
+ node->rbraceToken = loc(7);
node->isGenerator = true;
sym(1).Node = node;
} break;
./
-GeneratorExpression: T_FUNCTION T_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+GeneratorExpression: T_FUNCTION_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(4).FormalParameterList, sym(7).StatementList);
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
node->functionToken = loc(1);
+ if (!stringRef(2).isNull())
+ node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
node->lbraceToken = loc(6);
@@ -4040,6 +3992,20 @@ GeneratorExpression: T_FUNCTION T_STAR GeneratorLParen FormalParameters T_RPAREN
} break;
./
+GeneratorExpression: T_FUNCTION_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+/.
+ case $rule_number: {
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
+ node->functionToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->lbraceToken = loc(5);
+ node->rbraceToken = loc(7);
+ node->isGenerator = true;
+ sym(1).Node = node;
+ } break;
+./
+
GeneratorBody: FunctionBody;
YieldExpression: T_YIELD;
@@ -4419,7 +4385,7 @@ ExportDeclarationLookahead: ;
/.
case $rule_number: {
int token = lookaheadToken(lexer);
- if (token == T_FUNCTION || token == T_CLASS)
+ if (token == T_FUNCTION || token == T_FUNCTION_STAR || token == T_CLASS)
pushToken(T_FORCE_DECLARATION);
} break;
./
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index b63b2191b9..03355b3e38 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -105,6 +105,12 @@ ClassExpression *Node::asClassDefinition()
return nullptr;
}
+bool Node::ignoreRecursionDepth() const
+{
+ static const bool doIgnore = qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW");
+ return doIgnore;
+}
+
ExpressionNode *ExpressionNode::expressionCast()
{
return this;
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 39194068bf..e436c4673d 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -275,10 +275,16 @@ public:
virtual FunctionExpression *asFunctionDefinition();
virtual ClassExpression *asClassDefinition();
+ bool ignoreRecursionDepth() const;
+
inline void accept(Visitor *visitor)
{
Visitor::RecursionDepthCheck recursionCheck(visitor);
- if (recursionCheck()) {
+
+ // Stack overflow is uncommon, ignoreRecursionDepth() only returns true if
+ // QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line.
+ // Therefore, check for ignoreRecursionDepth() _after_ calling the inline recursionCheck().
+ if (recursionCheck() || ignoreRecursionDepth()) {
if (visitor->preVisit(this))
accept0(visitor);
visitor->postVisit(this);
@@ -307,6 +313,14 @@ public:
int kind = Kind_Undefined;
};
+template<typename T>
+T lastListElement(T head)
+{
+ auto current = head;
+ while (current->next)
+ current = current->next;
+ return current;
+}
class QML_PARSER_EXPORT UiQualifiedId: public Node
{
@@ -338,7 +352,7 @@ public:
{ return identifierToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : identifierToken; }
+ { return lastListElement(this)->identifierToken; }
// attributes
UiQualifiedId *next;
@@ -397,7 +411,7 @@ public:
{ return typeId->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : typeId->lastSourceLocation(); }
+ { return lastListElement(this)->typeId->lastSourceLocation(); }
inline TypeArgumentList *finish()
{
@@ -678,7 +692,10 @@ public:
{ return literalToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : (expression ? expression->lastSourceLocation() : literalToken); }
+ {
+ auto last = lastListElement(this);
+ return (last->expression ? last->expression->lastSourceLocation() : last->literalToken);
+ }
void accept0(Visitor *visitor) override;
@@ -800,7 +817,7 @@ public:
{ return commaToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : commaToken; }
+ { return lastListElement(this)->commaToken; }
inline Elision *finish ()
{
@@ -961,7 +978,10 @@ public:
{ return elision ? elision->firstSourceLocation() : element->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : (element ? element->lastSourceLocation() : elision->lastSourceLocation()); }
+ {
+ auto last = lastListElement(this);
+ return last->element ? last->element->lastSourceLocation() : last->elision->lastSourceLocation();
+ }
Elision *elision = nullptr;
PatternElement *element = nullptr;
@@ -1036,7 +1056,7 @@ public:
{ return property->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : property->lastSourceLocation(); }
+ { return lastListElement(this)->property->lastSourceLocation(); }
PatternProperty *property;
PatternPropertyList *next;
@@ -1645,7 +1665,9 @@ public:
{ return statement->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : statement->lastSourceLocation(); }
+ {
+ return lastListElement(this)->statement->lastSourceLocation();
+ }
inline StatementList *finish ()
{
@@ -2138,7 +2160,9 @@ public:
{ return clause->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : clause->lastSourceLocation(); }
+ {
+ return lastListElement(this)->clause->lastSourceLocation();
+ }
inline CaseClauses *finish ()
{
@@ -2429,7 +2453,9 @@ public:
{ return element->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : element->lastSourceLocation(); }
+ {
+ return lastListElement(this)->element->lastSourceLocation();
+ }
FormalParameterList *finish(MemoryPool *pool);
@@ -2606,7 +2632,9 @@ public:
{ return importSpecifierToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : importSpecifierToken; }
+ {
+ return lastListElement(this)->importSpecifierToken;
+ }
// attributes
SourceLocation importSpecifierToken;
@@ -2843,7 +2871,7 @@ public:
SourceLocation firstSourceLocation() const override
{ return exportSpecifier->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : exportSpecifier->lastSourceLocation(); }
+ { return lastListElement(this)->exportSpecifier->lastSourceLocation(); }
// attributes
ExportSpecifier *exportSpecifier;
@@ -2997,7 +3025,6 @@ public:
QStringRef importId;
SourceLocation importToken;
SourceLocation fileNameToken;
- SourceLocation versionToken;
SourceLocation asToken;
SourceLocation importIdToken;
SourceLocation semicolonToken;
@@ -3036,7 +3063,7 @@ public:
{ return member->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : member->lastSourceLocation(); }
+ { return lastListElement(this)->member->lastSourceLocation(); }
UiObjectMemberList *finish()
{
@@ -3115,7 +3142,7 @@ public:
{ return headerItem->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : headerItem->lastSourceLocation(); }
+ { return lastListElement(this)->headerItem->lastSourceLocation(); }
// attributes
Node *headerItem;
@@ -3179,7 +3206,7 @@ public:
{ return member->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : member->lastSourceLocation(); }
+ { return lastListElement(this)->member->lastSourceLocation(); }
UiArrayMemberList *finish()
{
@@ -3240,7 +3267,10 @@ public:
{ return colonToken.isValid() ? identifierToken : propertyTypeToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : (colonToken.isValid() ? propertyTypeToken : identifierToken); }
+ {
+ auto last = lastListElement(this);
+ return (last->colonToken.isValid() ? last->propertyTypeToken : last->identifierToken);
+ }
inline UiParameterList *finish ()
{
@@ -3283,6 +3313,8 @@ public:
return defaultToken;
else if (readonlyToken.isValid())
return readonlyToken;
+ else if (requiredToken.isValid())
+ return requiredToken;
return propertyToken;
}
@@ -3306,10 +3338,13 @@ public:
UiObjectMember *binding; // initialized with a QML object or array.
bool isDefaultMember;
bool isReadonlyMember;
+ bool isRequired = false;
UiParameterList *parameters;
+ // TODO: merge source locations
SourceLocation defaultToken;
SourceLocation readonlyToken;
SourceLocation propertyToken;
+ SourceLocation requiredToken;
SourceLocation typeModifierToken;
SourceLocation typeToken;
SourceLocation identifierToken;
@@ -3493,8 +3528,10 @@ public:
{ return memberToken; }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() :
- valueToken.isValid() ? valueToken : memberToken; }
+ {
+ auto last = lastListElement(this);
+ return last->valueToken.isValid() ? last->valueToken : last->memberToken;
+ }
void accept0(Visitor *visitor) override;
diff --git a/src/qml/parser/qqmljskeywords_p.h b/src/qml/parser/qqmljskeywords_p.h
index 96b3709162..3eb054341f 100644
--- a/src/qml/parser/qqmljskeywords_p.h
+++ b/src/qml/parser/qqmljskeywords_p.h
@@ -743,6 +743,18 @@ static inline int classify8(const QChar *s, int parseModeFlags) {
}
}
}
+ } else if (s[2].unicode() == 'q') {
+ if (s[3].unicode() == 'u') {
+ if (s[4].unicode() == 'i') {
+ if (s[5].unicode() == 'r') {
+ if (s[6].unicode() == 'e') {
+ if (s[7].unicode() == 'd') {
+ return Lexer::T_REQUIRED;
+ }
+ }
+ }
+ }
+ }
}
}
}
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 1e0ac72bd1..443e1a7476 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -492,6 +492,42 @@ int Lexer::scanToken()
again:
_validTokenText = false;
+ // handle comment can be called after a '/' has been read
+ // and returns true if it actually encountered a comment
+ auto handleComment = [this](){
+ if (_char == QLatin1Char('*')) {
+ scanChar();
+ while (_codePtr <= _endPtr) {
+ if (_char == QLatin1Char('*')) {
+ scanChar();
+ if (_char == QLatin1Char('/')) {
+ scanChar();
+
+ if (_engine) {
+ _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4,
+ tokenStartLine(), tokenStartColumn() + 2);
+ }
+
+ return true;
+ }
+ } else {
+ scanChar();
+ }
+ }
+ } else if (_char == QLatin1Char('/')) {
+ while (_codePtr <= _endPtr && !isLineTerminator()) {
+ scanChar();
+ }
+ if (_engine) {
+ _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2,
+ tokenStartLine(), tokenStartColumn() + 2);
+ }
+ return true;
+ }
+ return false;
+ };
+
+
while (_char.isSpace()) {
if (isLineTerminator()) {
if (_restrictedKeyword) {
@@ -599,35 +635,9 @@ again:
case ':': return T_COLON;
case '/':
- if (_char == QLatin1Char('*')) {
- scanChar();
- while (_codePtr <= _endPtr) {
- if (_char == QLatin1Char('*')) {
- scanChar();
- if (_char == QLatin1Char('/')) {
- scanChar();
-
- if (_engine) {
- _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4,
- tokenStartLine(), tokenStartColumn() + 2);
- }
-
- goto again;
- }
- } else {
- scanChar();
- }
- }
- } else if (_char == QLatin1Char('/')) {
- while (_codePtr <= _endPtr && !isLineTerminator()) {
- scanChar();
- }
- if (_engine) {
- _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2,
- tokenStartLine(), tokenStartColumn() + 2);
- }
+ if (handleComment())
goto again;
- } if (_char == QLatin1Char('=')) {
+ else if (_char == QLatin1Char('=')) {
scanChar();
return T_DIVIDE_EQ;
}
@@ -829,6 +839,21 @@ again:
if (!identifierWithEscapeChars)
kind = classify(_tokenStartPtr, _tokenLength, parseModeFlags());
+ if (kind == T_FUNCTION) {
+ continue_skipping:
+ while (_codePtr < _endPtr && _char.isSpace())
+ scanChar();
+ if (_char == QLatin1Char('*')) {
+ _tokenLength = _codePtr - _tokenStartPtr - 1;
+ kind = T_FUNCTION_STAR;
+ scanChar();
+ } else if (_char == QLatin1Char('/')) {
+ scanChar();
+ if (handleComment())
+ goto continue_skipping;
+ }
+ }
+
if (_engine) {
if (kind == T_IDENTIFIER && identifierWithEscapeChars)
_tokenSpell = _engine->newStringRef(_tokenText);
@@ -1407,6 +1432,7 @@ static const int uriTokens[] = {
QQmlJSGrammar::T_FINALLY,
QQmlJSGrammar::T_FOR,
QQmlJSGrammar::T_FUNCTION,
+ QQmlJSGrammar::T_FUNCTION_STAR,
QQmlJSGrammar::T_IF,
QQmlJSGrammar::T_IN,
QQmlJSGrammar::T_OF,
diff --git a/src/qml/qml/ftw/qintrusivelist.cpp b/src/qml/qml/ftw/qintrusivelist.cpp
index eb337a4de0..2ebaffb375 100644
--- a/src/qml/qml/ftw/qintrusivelist.cpp
+++ b/src/qml/qml/ftw/qintrusivelist.cpp
@@ -150,6 +150,10 @@ Returns an STL-style iterator pointing to the imaginary item after the last item
Remove the current object from the list, and return an iterator to the next element.
*/
+/*!
+ \class QIntrusiveListNode
+ \internal
+*/
/*!
\fn QIntrusiveListNode::QIntrusiveListNode()
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 8a50b51b5d..a33936647f 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -61,7 +61,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
//From qqml.h
bool qmlProtectModule(const char *uri, int majVersion)
{
- return QQmlMetaType::protectModule(uri, majVersion);
+ return QQmlMetaType::protectModule(QString::fromUtf8(uri), majVersion);
}
//From qqml.h
@@ -79,6 +79,13 @@ int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *q
// From qqmlprivate.h
QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJSEngine *)
{
+ if (!m_object) {
+ QQmlError error;
+ error.setDescription(QLatin1String("The registered singleton has already been deleted. Ensure that it outlives the engine."));
+ QQmlEnginePrivate::get(qeng)->warning(qeng, error);
+ return nullptr;
+ }
+
if (qeng->thread() != m_object->thread()) {
QQmlError error;
error.setDescription(QLatin1String("Registered object must live in the same thread as the engine it was registered with"));
@@ -96,33 +103,188 @@ QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJS
return m_object;
};
+static QVector<int> availableRevisions(const QMetaObject *metaObject)
+{
+ QVector<int> revisions;
+ if (!metaObject)
+ return revisions;
+ const int propertyOffset = metaObject->propertyOffset();
+ const int propertyCount = metaObject->propertyCount();
+ for (int propertyIndex = propertyOffset, propertyEnd = propertyOffset + propertyCount;
+ propertyIndex < propertyEnd; ++propertyIndex) {
+ const QMetaProperty property = metaObject->property(propertyIndex);
+ if (int revision = property.revision())
+ revisions.append(revision);
+ }
+ const int methodOffset = metaObject->methodOffset();
+ const int methodCount = metaObject->methodCount();
+ for (int methodIndex = methodOffset, methodEnd = methodOffset + methodCount;
+ methodIndex < methodEnd; ++methodIndex) {
+ const QMetaMethod method = metaObject->method(methodIndex);
+ if (int revision = method.revision())
+ revisions.append(revision);
+ }
+
+ // Need to also check parent meta objects, as their revisions are inherited.
+ if (const QMetaObject *superMeta = metaObject->superClass())
+ revisions += availableRevisions(superMeta);
+
+ return revisions;
+}
+
/*
This method is "over generalized" to allow us to (potentially) register more types of things in
the future without adding exported symbols.
*/
int QQmlPrivate::qmlregister(RegistrationType type, void *data)
{
- if (type == AutoParentRegistration) {
+ QQmlType dtype;
+ switch (type) {
+ case AutoParentRegistration:
return QQmlMetaType::registerAutoParentFunction(
*reinterpret_cast<RegisterAutoParent *>(data));
- } else if (type == QmlUnitCacheHookRegistration) {
+ case QmlUnitCacheHookRegistration:
return QQmlMetaType::registerUnitCacheHook(
*reinterpret_cast<RegisterQmlUnitCacheHook *>(data));
+ case TypeAndRevisionsRegistration: {
+ const RegisterTypeAndRevisions &type = *reinterpret_cast<RegisterTypeAndRevisions *>(data);
+ const char *elementName = classElementName(type.classInfoMetaObject);
+ const bool creatable = (elementName != nullptr)
+ && boolClassInfo(type.classInfoMetaObject, "QML.Creatable", true);
+
+ const QString noCreateReason = creatable
+ ? QString()
+ : QString::fromUtf8(classInfo(type.classInfoMetaObject, "QML.UncreatableReason"));
+ RegisterType revisionRegistration = {
+ 1,
+ type.typeId,
+ type.listId,
+ creatable ? type.objectSize : 0,
+ nullptr,
+ noCreateReason,
+ type.uri,
+ type.versionMajor,
+ -1,
+ nullptr,
+ type.metaObject,
+ type.attachedPropertiesFunction,
+ type.attachedPropertiesMetaObject,
+ type.parserStatusCast,
+ type.valueSourceCast,
+ type.valueInterceptorCast,
+ type.extensionObjectCreate,
+ type.extensionMetaObject,
+ nullptr,
+ -1
+ };
+
+ const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0);
+ const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1);
+
+ auto revisions = availableRevisions(type.metaObject);
+ revisions.append(qMax(added, 0));
+ if (type.attachedPropertiesMetaObject)
+ revisions += availableRevisions(type.attachedPropertiesMetaObject);
+
+ std::sort(revisions.begin(), revisions.end());
+ const auto it = std::unique(revisions.begin(), revisions.end());
+ revisions.erase(it, revisions.end());
+
+ const bool typeWasRemoved = removed >= added;
+ for (int revision : revisions) {
+ if (revision < added)
+ continue;
+
+ // When removed, we still add revisions, but anonymous ones
+ if (typeWasRemoved && revision >= removed) {
+ revisionRegistration.elementName = nullptr;
+ revisionRegistration.create = nullptr;
+ } else {
+ revisionRegistration.elementName = elementName;
+ revisionRegistration.create = creatable ? type.create : nullptr;
+ }
+
+ // Equivalent of qmlRegisterRevision<T, revision>(...)
+ revisionRegistration.versionMinor = revision;
+ revisionRegistration.revision = revision;
+ revisionRegistration.customParser = type.customParserFactory();
+
+ qmlregister(TypeRegistration, &revisionRegistration);
+ }
+ break;
}
+ case SingletonAndRevisionsRegistration: {
+ const RegisterSingletonTypeAndRevisions &type
+ = *reinterpret_cast<RegisterSingletonTypeAndRevisions *>(data);
+ const char *elementName = classElementName(type.classInfoMetaObject);
+ RegisterSingletonType revisionRegistration = {
+ QmlCurrentSingletonTypeRegistrationVersion,
+ type.uri,
+ type.versionMajor,
+ -1,
+ elementName,
- QQmlType dtype;
- if (type == TypeRegistration)
+ type.scriptApi,
+ nullptr,
+ type.instanceMetaObject,
+ type.typeId,
+ -1,
+
+ type.generalizedQobjectApi
+ };
+
+ const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0);
+ const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1);
+
+ auto revisions = availableRevisions(type.instanceMetaObject);
+ revisions.append(qMax(added, 0));
+
+ std::sort(revisions.begin(), revisions.end());
+ const auto it = std::unique(revisions.begin(), revisions.end());
+ revisions.erase(it, revisions.end());
+
+ const bool typeWasRemoved = removed >= added;
+ for (int revision : qAsConst(revisions)) {
+ if (revision < added)
+ continue;
+
+ // When removed, we still add revisions, but anonymous ones
+ if (typeWasRemoved && revision >= removed) {
+ revisionRegistration.typeName = nullptr;
+ revisionRegistration.scriptApi = nullptr;
+ revisionRegistration.generalizedQobjectApi = nullptr;
+ } else {
+ revisionRegistration.typeName = elementName;
+ revisionRegistration.scriptApi = type.scriptApi;
+ revisionRegistration.generalizedQobjectApi = type.generalizedQobjectApi;
+ }
+
+ // Equivalent of qmlRegisterRevision<T, revision>(...)
+ revisionRegistration.versionMinor = revision;
+ revisionRegistration.revision = revision;
+
+ qmlregister(SingletonRegistration, &revisionRegistration);
+ }
+ break;
+ }
+ case TypeRegistration:
dtype = QQmlMetaType::registerType(*reinterpret_cast<RegisterType *>(data));
- else if (type == InterfaceRegistration)
+ break;
+ case InterfaceRegistration:
dtype = QQmlMetaType::registerInterface(*reinterpret_cast<RegisterInterface *>(data));
- else if (type == SingletonRegistration)
+ break;
+ case SingletonRegistration:
dtype = QQmlMetaType::registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data));
- else if (type == CompositeRegistration)
+ break;
+ case CompositeRegistration:
dtype = QQmlMetaType::registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data));
- else if (type == CompositeSingletonRegistration)
+ break;
+ case CompositeSingletonRegistration:
dtype = QQmlMetaType::registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data));
- else
+ break;
+ default:
return -1;
+ }
if (!dtype.isValid())
return -1;
@@ -148,6 +310,14 @@ void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data)
case CompositeSingletonRegistration:
QQmlMetaType::unregisterType(data);
break;
+ case TypeAndRevisionsRegistration:
+ case SingletonAndRevisionsRegistration:
+ // Currently unnecessary. We'd need a special data structure to hold
+ // URI + majorVersion and then we'd iterate the minor versions, look up the
+ // associated QQmlType objects by uri/elementName/major/minor and qmlunregister
+ // each of them.
+ Q_UNREACHABLE();
+ break;
}
}
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index a93b012c70..ae3893dd73 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -41,9 +41,6 @@
#define QQML_H
#include <QtQml/qqmlprivate.h>
-#include <QtQml/qqmlparserstatus.h>
-#include <QtQml/qqmlpropertyvaluesource.h>
-#include <QtQml/qqmllist.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qmetaobject.h>
@@ -51,6 +48,12 @@
#define QML_VERSION 0x020000
#define QML_VERSION_STR "2.0"
+#define QML_PRIVATE_NAMESPACE \
+ QT_PREPEND_NAMESPACE(QQmlPrivate)
+
+#define QML_REGISTER_TYPES_AND_REVISIONS \
+ QT_PREPEND_NAMESPACE(qmlRegisterTypesAndRevisions)
+
#define QML_DECLARE_TYPE(TYPE) \
Q_DECLARE_METATYPE(TYPE *) \
Q_DECLARE_METATYPE(QQmlListProperty<TYPE>)
@@ -64,6 +67,52 @@
#define QML_DECLARE_INTERFACE_HASMETATYPE(INTERFACE) \
QML_DECLARE_TYPE_HASMETATYPE(INTERFACE)
+#define QML_ELEMENT \
+ Q_CLASSINFO("QML.Element", "auto")
+
+#define QML_ANONYMOUS \
+ Q_CLASSINFO("QML.Element", "anonymous")
+
+#define QML_NAMED_ELEMENT(NAME) \
+ Q_CLASSINFO("QML.Element", #NAME)
+
+#define QML_UNCREATABLE(REASON) \
+ Q_CLASSINFO("QML.Creatable", "false") \
+ Q_CLASSINFO("QML.UncreatableReason", REASON)
+
+#define QML_SINGLETON \
+ Q_CLASSINFO("QML.Singleton", "true") \
+ enum class QmlIsSingleton {yes = true}; \
+ template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlSingleton; \
+ template<typename T, typename... Args> \
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+
+#define QML_ADDED_IN_MINOR_VERSION(VERSION) \
+ Q_CLASSINFO("QML.AddedInMinorVersion", #VERSION)
+
+#define QML_REMOVED_IN_MINOR_VERSION(VERSION) \
+ Q_CLASSINFO("QML.RemovedInMinorVersion", #VERSION)
+
+#define QML_ATTACHED(ATTACHED_TYPE) \
+ Q_CLASSINFO("QML.Attached", #ATTACHED_TYPE) \
+ using QmlAttachedType = ATTACHED_TYPE; \
+ template<class, class, bool> friend struct QML_PRIVATE_NAMESPACE::QmlAttached; \
+ template<class> friend struct QML_PRIVATE_NAMESPACE::QmlAttachedAccessor;
+
+#define QML_EXTENDED(EXTENDED_TYPE) \
+ Q_CLASSINFO("QML.Extended", #EXTENDED_TYPE) \
+ using QmlExtendedType = EXTENDED_TYPE; \
+ template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlExtended; \
+ template<typename T, typename... Args> \
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+
+#define QML_FOREIGN(FOREIGN_TYPE) \
+ Q_CLASSINFO("QML.Foreign", #FOREIGN_TYPE) \
+ using QmlForeignType = FOREIGN_TYPE; \
+ template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlResolved; \
+ template<typename T, typename... Args> \
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+
enum { /* TYPEINFO flags */
QML_HAS_ATTACHED_PROPERTIES = 0x01
};
@@ -82,27 +131,13 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
-
-class QQmlPropertyValueInterceptor;
-
-#define QML_GETTYPENAMES \
- const char *className = T::staticMetaObject.className(); \
- const int nameLen = int(strlen(className)); \
- QVarLengthArray<char,48> pointerName(nameLen+2); \
- memcpy(pointerName.data(), className, size_t(nameLen)); \
- pointerName[nameLen] = '*'; \
- pointerName[nameLen+1] = '\0'; \
- const int listLen = int(strlen("QQmlListProperty<")); \
- QVarLengthArray<char,64> listName(listLen + nameLen + 2); \
- memcpy(listName.data(), "QQmlListProperty<", size_t(listLen)); \
- memcpy(listName.data()+listLen, className, size_t(nameLen)); \
- listName[listLen+nameLen] = '>'; \
- listName[listLen+nameLen+1] = '\0';
-
void Q_QML_EXPORT qmlClearTypeRegistrations();
+template<class T>
+QQmlCustomParser *qmlCreateCustomParser();
+
template<typename T>
-int qmlRegisterAnonymousType(const char *uri, int versionMajor=1)
+int qmlRegisterAnonymousType(const char *uri, int versionMajor)
{
QML_GETTYPENAMES
@@ -133,11 +168,13 @@ int qmlRegisterAnonymousType(const char *uri, int versionMajor=1)
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
+#if QT_DEPRECATED_SINCE(5, 14)
template<typename T>
QT_DEPRECATED_VERSION_X_5_14("Use qmlRegisterAnonymousType instead") int qmlRegisterType()
{
- return qmlRegisterAnonymousType<T>("");
+ return qmlRegisterAnonymousType<T>("", 1);
}
+#endif
int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message);
@@ -586,8 +623,10 @@ namespace QtQml {
Q_QML_EXPORT QQmlContext *qmlContext(const QObject *);
Q_QML_EXPORT QQmlEngine *qmlEngine(const QObject *);
#if QT_DEPRECATED_SINCE(5, 14)
- Q_QML_EXPORT QT_DEPRECATED QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true);
- Q_QML_EXPORT QT_DEPRECATED QObject *qmlAttachedPropertiesObject(
+ Q_QML_EXPORT QT_DEPRECATED_VERSION_X_5_14("Use qmlAttachedPropertiesObject(QObject *, QQmlAttachedPropertiesFunc, bool")
+ QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true);
+ Q_QML_EXPORT QT_DEPRECATED_VERSION_X_5_14("Use qmlAttachedPropertiesObject(QObject *, QQmlAttachedPropertiesFunc, bool")
+ QObject *qmlAttachedPropertiesObject(
int *, const QObject *, const QMetaObject *, bool create);
#endif
Q_QML_EXPORT QQmlAttachedPropertiesFunc qmlAttachedPropertiesFunction(QObject *,
@@ -720,6 +759,44 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i
return QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &type);
}
+template<class T, class Resolved, class Extended, bool Singleton>
+struct QmlTypeAndRevisionsRegistration;
+
+template<class T, class Resolved, class Extended>
+struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false> {
+ static void registerTypeAndRevisions(const char *uri, int versionMajor)
+ {
+ QQmlPrivate::qmlRegisterTypeAndRevisions<Resolved, Extended>(
+ uri, versionMajor, &T::staticMetaObject);
+ }
+};
+
+template<class T, class Resolved>
+struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true> {
+ static void registerTypeAndRevisions(const char *uri, int versionMajor)
+ {
+ QQmlPrivate::qmlRegisterSingletonAndRevisions<Resolved>(
+ uri, versionMajor, &T::staticMetaObject);
+ }
+};
+
+template<typename T = void, typename... Args>
+void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor);
+
+template<typename T, typename... Args>
+void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor)
+{
+ QmlTypeAndRevisionsRegistration<
+ T, typename QQmlPrivate::QmlResolved<T>::Type,
+ typename QQmlPrivate::QmlExtended<T>::Type,
+ QQmlPrivate::QmlSingleton<T>::Value>
+ ::registerTypeAndRevisions(uri, versionMajor);
+ qmlRegisterTypesAndRevisions<Args...>(uri, versionMajor);
+}
+
+template<>
+inline void qmlRegisterTypesAndRevisions<>(const char *, int) {}
+
int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index d04a89b514..adb036e2d0 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -279,7 +279,7 @@ void QQmlApplicationEngine::load(const QString &filePath)
}
/*!
- Sets the initial properties with which the QML component gets initialized after
+ Sets the \a initialProperties with which the QML component gets initialized after
it gets loaded.
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 3a437eab8d..2f6aabf61e 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -315,7 +315,7 @@ protected:
break;
default:
if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->metaType.id() == pd->propType()) {
+ if (vtw->d()->valueType()->metaType.id() == pd->propType()) {
return vtw->write(m_target.data(), pd->coreIndex());
}
}
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index ed8c41a582..f03f90e7f3 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -340,6 +340,16 @@ void QQmlComponentPrivate::fromTypeData(const QQmlRefPointer<QQmlTypeData> &data
}
}
+RequiredProperties &QQmlComponentPrivate::requiredProperties()
+{
+ return state.creator->requiredProperties();
+}
+
+bool QQmlComponentPrivate::hadRequiredProperties() const
+{
+ return state.creator->componentHadRequiredProperties();
+}
+
void QQmlComponentPrivate::clear()
{
if (typeData) {
@@ -364,8 +374,8 @@ QObject *QQmlComponentPrivate::doBeginCreate(QQmlComponent *q, QQmlContext *cont
bool QQmlComponentPrivate::setInitialProperty(QObject *component, const QString& name, const QVariant &value)
{
- QQmlProperty prop(component, name);
- auto privProp = QQmlPropertyPrivate::get(prop);
+ QQmlProperty prop = QQmlComponentPrivate::removePropertyFromRequired(component, name, requiredProperties());
+ QQmlPropertyPrivate *privProp = QQmlPropertyPrivate::get(prop);
if (!prop.isValid() || !privProp->writeValueProperty(value, nullptr)) {
QQmlError error{};
error.setUrl(url);
@@ -809,12 +819,17 @@ QObject *QQmlComponent::create(QQmlContext *context)
QObject *rv = d->doBeginCreate(this, context);
if (rv)
completeCreate();
+ if (rv && !d->requiredProperties().empty()) {
+ delete rv;
+ return nullptr;
+ }
return rv;
}
/*!
- Create an object instance of this component, and initialize its toplevel properties according to initalPropertyValues.
-
+ Create an object instance of this component, and initialize its toplevel
+ properties with \a initialProperties. \a context specifies the context
+ where the object instance is to be created.
\sa QQmlComponent::create
\since 5.14
@@ -828,6 +843,10 @@ QObject *QQmlComponent::createWithInitialProperties(const QVariantMap& initialPr
setInitialProperties(rv, initialProperties);
completeCreate();
}
+ if (!d->requiredProperties().empty()) {
+ d->requiredProperties().clear();
+ return nullptr;
+ }
return rv;
}
@@ -980,6 +999,57 @@ void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionS
}
/*!
+ * \internal
+ * Finds the matching toplevel property with name \a name of the component \a createdComponent.
+ * If it was a required property or an alias to a required property contained in \a
+ * requiredProperties, it is removed from it.
+ *
+ * If wasInRequiredProperties is non-null, the referenced boolean is set to true iff the property
+ * was found in requiredProperties.
+ *
+ * Returns the QQmlProperty with name \a name (which might be invalid if there is no such property),
+ * for further processing (for instance, actually setting the property value).
+ *
+ * Note: This method is used in QQmlComponent and QQmlIncubator to manage required properties. Most
+ * classes which create components should not need it and should only need to call
+ * setInitialProperties.
+ */
+QQmlProperty QQmlComponentPrivate::removePropertyFromRequired(QObject *createdComponent, const QString &name, RequiredProperties &requiredProperties, bool* wasInRequiredProperties)
+{
+ QQmlProperty prop(createdComponent, name);
+ auto privProp = QQmlPropertyPrivate::get(prop);
+ if (prop.isValid()) {
+ // resolve outstanding required properties
+ auto targetProp = &privProp->core;
+ if (targetProp->isAlias()) {
+ auto target = createdComponent;
+ QQmlPropertyIndex originalIndex(targetProp->coreIndex());
+ QQmlPropertyIndex propIndex;
+ QQmlPropertyPrivate::findAliasTarget(target, originalIndex, &target, &propIndex);
+ QQmlData *data = QQmlData::get(target);
+ Q_ASSERT(data && data->propertyCache);
+ targetProp = data->propertyCache->property(propIndex.coreIndex());
+ } else {
+ // we need to get the pointer from the property cache instead of directly using
+ // targetProp else the lookup will fail
+ QQmlData *data = QQmlData::get(createdComponent);
+ Q_ASSERT(data && data->propertyCache);
+ targetProp = data->propertyCache->property(targetProp->coreIndex());
+ }
+ auto it = requiredProperties.find(targetProp);
+ if (it != requiredProperties.end()) {
+ if (wasInRequiredProperties)
+ *wasInRequiredProperties = true;
+ requiredProperties.erase(it);
+ } else {
+ if (wasInRequiredProperties)
+ *wasInRequiredProperties = false;
+ }
+ }
+ return prop;
+}
+
+/*!
This method provides advanced control over component instance creation.
In general, programmers should use QQmlComponent::create() to create a
component.
@@ -998,6 +1068,11 @@ void QQmlComponent::completeCreate()
void QQmlComponentPrivate::completeCreate()
{
+ const RequiredProperties& unsetRequiredProperties = requiredProperties();
+ for (const auto& unsetRequiredProperty: unsetRequiredProperties) {
+ QQmlError error = unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
+ state.errors.push_back(error);
+ }
if (state.completePending) {
++creationDepth.localData();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
@@ -1104,7 +1179,7 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
}
/*!
- Set toplevel properties of the component.
+ Set toplevel \a properties of the \a component.
This method provides advanced control over component instance creation.
@@ -1185,7 +1260,7 @@ struct QmlIncubatorObject : public QV4::Object
static ReturnedValue method_forceCompletion(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
void statusChanged(QQmlIncubator::Status);
- void setInitialState(QObject *);
+ void setInitialState(QObject *, RequiredProperties &requiredProperties);
};
}
@@ -1210,7 +1285,8 @@ public:
void setInitialState(QObject *o) override {
QV4::Scope scope(incubatorObject.engine());
QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject.as<QV4::QmlIncubatorObject>());
- i->setInitialState(o);
+ auto d = QQmlIncubatorPrivate::get(this);
+ i->setInitialState(o, d->requiredProperties());
}
QV4::PersistentValue incubatorObject; // keep a strong internal reference while incubating
@@ -1282,7 +1358,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
*/
-void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v)
+void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties &requiredProperties, QObject *createdComponent)
{
QV4::Scope scope(engine);
QV4::ScopedObject object(scope);
@@ -1301,6 +1377,7 @@ void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV
break;
object = o;
const QStringList properties = name->toQString().split(QLatin1Char('.'));
+ bool isTopLevelProperty = properties.size() == 1;
for (int i = 0; i < properties.length() - 1; ++i) {
name = engine->newString(properties.at(i));
object = object->get(name);
@@ -1317,12 +1394,40 @@ void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV
if (engine->hasException) {
engine->hasException = false;
continue;
+ } else if (isTopLevelProperty) {
+ auto prop = removePropertyFromRequired(createdComponent, name->toQString(), requiredProperties);
}
}
engine->hasException = false;
}
+QQmlError QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(const RequiredPropertyInfo &unsetRequiredProperty)
+{
+ QQmlError error;
+ QString description = QLatin1String("Required property %1 was not initialized").arg(unsetRequiredProperty.propertyName);
+ switch (unsetRequiredProperty.aliasesToRequired.size()) {
+ case 0:
+ break;
+ case 1: {
+ const auto info = unsetRequiredProperty.aliasesToRequired.first();
+ description += QLatin1String("\nIt can be set via the alias property %1 from %2\n").arg(info.propertyName, info.fileUrl.toString());
+ break;
+ }
+ default:
+ description += QLatin1String("\nIt can be set via one of the following alias properties:");
+ for (auto aliasInfo: unsetRequiredProperty.aliasesToRequired) {
+ description += QLatin1String("\n- %1 (%2)").arg(aliasInfo.propertyName, aliasInfo.fileUrl.toString());
+ }
+ description += QLatin1Char('\n');
+ }
+ error.setDescription(description);
+ error.setUrl(unsetRequiredProperty.fileUrl);
+ error.setLine(unsetRequiredProperty.location.line);
+ error.setColumn(unsetRequiredProperty.location.column);
+ return error;
+}
+
/*!
\internal
*/
@@ -1370,7 +1475,17 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (!valuemap->isUndefined()) {
QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->qmlContext());
- QQmlComponentPrivate::setInitialProperties(v4, qmlContext, object, valuemap);
+ QQmlComponentPrivate::setInitialProperties(v4, qmlContext, object, valuemap, d->requiredProperties(), rv);
+ }
+ if (!d->requiredProperties().empty()) {
+ QList<QQmlError> errors;
+ for (const auto &requiredProperty: d->requiredProperties()) {
+ errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(requiredProperty));
+ }
+ qmlWarning(rv, errors);
+ args->setReturnValue(QV4::Encode::null());
+ delete rv;
+ return;
}
d->completeCreate();
@@ -1502,7 +1617,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
}
// XXX used by QSGLoader
-void QQmlComponentPrivate::initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate)
+void QQmlComponentPrivate::initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties &requiredProperties)
{
QV4::ExecutionEngine *v4engine = engine->handle();
QV4::Scope scope(v4engine);
@@ -1511,7 +1626,7 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(QV4::QmlContext
Q_ASSERT(object->as<QV4::Object>());
if (!valuemap.isUndefined())
- setInitialProperties(v4engine, qmlContext, object, valuemap);
+ setInitialProperties(v4engine, qmlContext, object, valuemap, requiredProperties, toCreate);
}
QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
@@ -1601,7 +1716,7 @@ void QV4::Heap::QmlIncubatorObject::destroy() {
Object::destroy();
}
-void QV4::QmlIncubatorObject::setInitialState(QObject *o)
+void QV4::QmlIncubatorObject::setInitialState(QObject *o, RequiredProperties &requiredProperties)
{
QQmlComponent_setQmlParent(o, d()->parent);
@@ -1610,7 +1725,7 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
QV4::Scope scope(v4);
QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
QV4::Scoped<QV4::QmlContext> qmlCtxt(scope, d()->qmlContext);
- QQmlComponentPrivate::setInitialProperties(v4, qmlCtxt, obj, d()->valuemap);
+ QQmlComponentPrivate::setInitialProperties(v4, qmlCtxt, obj, d()->valuemap, requiredProperties, o);
}
}
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index f259c99b08..cb5d5a787c 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -70,6 +70,9 @@ class Q_QML_EXPORT QQmlComponent : public QObject
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl url READ url CONSTANT)
+ QML_NAMED_ELEMENT(Component)
+ QML_ATTACHED(QQmlComponentAttached)
+ Q_CLASSINFO("QML.Builtin", "QML")
public:
enum CompilationMode { PreferSynchronous, Asynchronous };
@@ -136,9 +139,29 @@ private:
friend class QQmlObjectCreator;
};
-QT_END_NAMESPACE
+// Don't do this at home.
+namespace QQmlPrivate {
+
+// Generally you cannot use QQmlComponentAttached as attached properties object in derived classes.
+// It is private.
+template<class T>
+struct OverridableAttachedType<T, QQmlComponentAttached>
+{
+ using Type = void;
+};
+
+// QQmlComponent itself is allowed to use QQmlComponentAttached, though.
+template<>
+struct OverridableAttachedType<QQmlComponent, QQmlComponentAttached>
+{
+ using Type = QQmlComponentAttached;
+};
+
+} // namespace QQmlPrivate
+
+
+QT_END_NAMESPACE
QML_DECLARE_TYPE(QQmlComponent)
-QML_DECLARE_TYPEINFO(QQmlComponent, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQMLCOMPONENT_H
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 2170646b89..a919eb45c0 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -86,8 +86,9 @@ public:
QObject *beginCreate(QQmlContextData *);
void completeCreate();
- void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate);
- static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v);
+ void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties &requiredProperties);
+ static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties &requiredProperties, QObject *createdComponent);
+ static QQmlError unsetRequiredPropertyToQQmlError(const RequiredPropertyInfo &unsetRequiredProperty);
virtual void incubateObject(
QQmlIncubator *incubationTask,
@@ -106,6 +107,8 @@ public:
qreal progress;
int start;
+ RequiredProperties& requiredProperties();
+ bool hadRequiredProperties() const;
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
struct ConstructionState {
@@ -134,6 +137,7 @@ public:
static void completeDeferred(QQmlEnginePrivate *enginePriv, DeferredState *deferredState);
static void complete(QQmlEnginePrivate *enginePriv, ConstructionState *state);
+ static QQmlProperty removePropertyFromRequired(QObject *createdComponent, const QString &name, RequiredProperties& requiredProperties, bool *wasInRequiredProperties = nullptr);
QQmlEngine *engine;
QQmlGuardedContextData creationContext;
diff --git a/src/qml/qml/qqmlcomponentattached_p.h b/src/qml/qml/qqmlcomponentattached_p.h
index e3bca18857..8ecd9da17d 100644
--- a/src/qml/qml/qqmlcomponentattached_p.h
+++ b/src/qml/qml/qqmlcomponentattached_p.h
@@ -61,6 +61,11 @@ QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QQmlComponentAttached : public QObject
{
Q_OBJECT
+
+ // Used as attached object for QQmlComponent. We want qqmlcomponentattached_p.h to be #include'd
+ // when registering QQmlComponent, but we cannot #include it from qqmlcomponent.h. Therefore we
+ // force an anonymous type registration here.
+ QML_ANONYMOUS
public:
QQmlComponentAttached(QObject *parent = nullptr);
~QQmlComponentAttached();
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 14892bd6ad..254b6cc3db 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -358,7 +358,7 @@ void QQmlContext::setContextProperties(const QVector<PropertyPair> &properties)
data->expressions = nullptr;
data->childContexts = nullptr;
- for (auto property : properties)
+ for (const auto &property : properties)
setContextProperty(property.name, property.value);
data->expressions = expressions;
@@ -550,7 +550,7 @@ QQmlContextData::QQmlContextData()
QQmlContextData::QQmlContextData(QQmlContext *ctxt)
: engine(nullptr), isInternal(false), isJSContext(false),
isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
- stronglyReferencedByParent(false), publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1),
+ stronglyReferencedByParent(false), hasExtraObject(false), publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1),
contextObject(nullptr), nextChild(nullptr), prevChild(nullptr),
expressions(nullptr), contextObjects(nullptr), idValues(nullptr), idValueCount(0),
componentAttached(nullptr)
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index 5f7316b00c..f93393a11b 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -147,11 +147,16 @@ public:
quint32 hasEmittedDestruction:1;
quint32 isRootObjectInCreation:1;
quint32 stronglyReferencedByParent:1;
- quint32 dummy:25;
+ quint32 hasExtraObject:1; // used in QQmlDelegateModelItem::dataForObject to find the corresponding QQmlDelegateModelItem of an object
+ quint32 dummy:24;
QQmlContext *publicContext;
- // The incubator that is constructing this context if any
- QQmlIncubatorPrivate *incubator;
+ union {
+ // The incubator that is constructing this context if any
+ QQmlIncubatorPrivate *incubator;
+ // a pointer to extra data, currently only used in QQmlDelegateModel
+ QObject *extraObject;
+ };
// Compilation unit for contexts that belong to a compiled type.
QQmlRefPointer<QV4::ExecutableCompilationUnit> typeCompilationUnit;
diff --git a/src/qml/qml/qqmldatablob.cpp b/src/qml/qml/qqmldatablob.cpp
index 2183721d32..750fc6de50 100644
--- a/src/qml/qml/qqmldatablob.cpp
+++ b/src/qml/qml/qqmldatablob.cpp
@@ -351,7 +351,7 @@ void QQmlDataBlob::addDependency(QQmlDataBlob *blob)
status() == Error || status() == Complete || m_isDone)
return;
- for (auto existingDep: qAsConst(m_waitingFor))
+ for (const auto &existingDep: qAsConst(m_waitingFor))
if (existingDep.data() == blob)
return;
diff --git a/src/qml/qml/qqmldatablob_p.h b/src/qml/qml/qqmldatablob_p.h
index da3bbe2c1f..0450e94c02 100644
--- a/src/qml/qml/qqmldatablob_p.h
+++ b/src/qml/qml/qqmldatablob_p.h
@@ -242,7 +242,9 @@ private:
mutable QString m_finalUrlString;
// List of QQmlDataBlob's that are waiting for me to complete.
+protected:
QList<QQmlDataBlob *> m_waitingOnMe;
+private:
// List of QQmlDataBlob's that I am waiting for to complete.
QVector<QQmlRefPointer<QQmlDataBlob>> m_waitingFor;
diff --git a/src/qml/qml/qqmldirdata.cpp b/src/qml/qml/qqmldirdata.cpp
index 7652cec322..de74dfdf9b 100644
--- a/src/qml/qml/qqmldirdata.cpp
+++ b/src/qml/qml/qqmldirdata.cpp
@@ -61,7 +61,7 @@ QQmlTypeLoader::Blob::PendingImportPtr QQmlQmldirData::import(QQmlTypeLoader::Bl
void QQmlQmldirData::setImport(QQmlTypeLoader::Blob *blob, QQmlTypeLoader::Blob::PendingImportPtr import)
{
- m_imports[blob] = import;
+ m_imports[blob] = std::move(import);
}
int QQmlQmldirData::priority(QQmlTypeLoader::Blob *blob) const
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index a6f7067552..1a868bfaa1 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -201,27 +201,19 @@ void QQmlEnginePrivate::defineModule()
{
const char uri[] = "QtQml";
- qmlRegisterType<QQmlComponent>(uri, 2, 0, "Component");
- qmlRegisterType<QObject>(uri, 2, 0, "QtObject");
- qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding");
- qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding"); // Only available in >= 2.8
- qmlRegisterType<QQmlBind, 14>(uri, 2, 14, "Binding");
-
- // TODO: We won't need Connections to be a custom type anymore once we can drop the
- // automatic signal handler inference from undeclared properties.
- qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser);
- qmlRegisterCustomType<QQmlConnections, 3>(uri, 2, 3, "Connections", new QQmlConnectionsParser); // Only available in QtQml >= 2.3
-
+ qmlRegisterTypesAndRevisions<
+ QObjectForeign,
#if QT_CONFIG(qml_animation)
- qmlRegisterType<QQmlTimer>(uri, 2, 0, "Timer");
+ QQmlTimer,
#endif
-
- qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory"); // Only available in >= 2.8
- qmlRegisterType<QQmlLoggingCategory, 12>(uri, 2, 12, "LoggingCategory"); // Only available in >= 2.12
-
#if QT_CONFIG(qml_locale)
- qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
+ QQmlLocale,
#endif
+ QQmlComponent,
+ QQmlBind,
+ QQmlConnections,
+ QQmlLoggingCategory
+ >(uri, 2);
}
bool QQmlEnginePrivate::designerMode()
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 2c4bb36c8f..98c7823921 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -101,6 +101,13 @@ class QQmlProfiler;
class QQmlPropertyCapture;
class QQmlMetaObject;
+struct QObjectForeign {
+ Q_GADGET
+ QML_FOREIGN(QObject)
+ QML_NAMED_ELEMENT(QtObject)
+ Q_CLASSINFO("QML.Root", "QML")
+};
+
// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
// The inline method definitions are in qqmljavascriptexpression_p.h
class QQmlJavaScriptExpressionGuard : public QQmlNotifierEndpoint
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 136159993a..3c540a6124 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -90,7 +90,7 @@ QT_BEGIN_NAMESPACE
\endcode
*/
#define qmlobject_connect(Sender, SenderType, Signal, Receiver, ReceiverType, Method) \
-{ \
+do { \
SenderType *sender = (Sender); \
ReceiverType *receiver = (Receiver); \
const char *signal = (Signal); \
@@ -98,11 +98,11 @@ QT_BEGIN_NAMESPACE
static int signalIdx = -1; \
static int methodIdx = -1; \
if (signalIdx < 0) { \
- Q_ASSERT(((int)(*signal) - '0') == QSIGNAL_CODE); \
+ Q_ASSERT((int(*signal) - '0') == QSIGNAL_CODE); \
signalIdx = SenderType::staticMetaObject.indexOfSignal(signal+1); \
} \
if (methodIdx < 0) { \
- int code = ((int)(*method) - '0'); \
+ int code = (int(*method) - '0'); \
Q_ASSERT(code == QSLOT_CODE || code == QSIGNAL_CODE); \
if (code == QSLOT_CODE) \
methodIdx = ReceiverType::staticMetaObject.indexOfSlot(method+1); \
@@ -111,7 +111,7 @@ QT_BEGIN_NAMESPACE
} \
Q_ASSERT(signalIdx != -1 && methodIdx != -1); \
QMetaObject::connect(sender, signalIdx, receiver, methodIdx, Qt::DirectConnection); \
-}
+} while (0)
/*!
Disconnect \a Signal of \a Sender from \a Method of \a Receiver. \a Signal must be
@@ -129,7 +129,7 @@ QT_BEGIN_NAMESPACE
\endcode
*/
#define qmlobject_disconnect(Sender, SenderType, Signal, Receiver, ReceiverType, Method) \
-{ \
+do { \
SenderType *sender = (Sender); \
ReceiverType *receiver = (Receiver); \
const char *signal = (Signal); \
@@ -137,11 +137,11 @@ QT_BEGIN_NAMESPACE
static int signalIdx = -1; \
static int methodIdx = -1; \
if (signalIdx < 0) { \
- Q_ASSERT(((int)(*signal) - '0') == QSIGNAL_CODE); \
+ Q_ASSERT((int(*signal) - '0') == QSIGNAL_CODE); \
signalIdx = SenderType::staticMetaObject.indexOfSignal(signal+1); \
} \
if (methodIdx < 0) { \
- int code = ((int)(*method) - '0'); \
+ int code = (int(*method) - '0'); \
Q_ASSERT(code == QSLOT_CODE || code == QSIGNAL_CODE); \
if (code == QSLOT_CODE) \
methodIdx = ReceiverType::staticMetaObject.indexOfSlot(method+1); \
@@ -150,7 +150,7 @@ QT_BEGIN_NAMESPACE
} \
Q_ASSERT(signalIdx != -1 && methodIdx != -1); \
QMetaObject::disconnect(sender, signalIdx, receiver, methodIdx); \
-}
+} while (0)
/*!
This method is identical to qobject_cast<T>() except that it does not require lazy
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 31a7004407..d69c2ac903 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -780,12 +780,12 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
typeStr + dotqml_string, // Type -> Type.qml
typeStr + dotuidotqml_string // Type -> Type.ui.qml
};
- for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) {
- exists = typeLoader->fileExists(localDirectoryPath, urlsToTry[i]);
+ for (const QString &urlToTry : urlsToTry) {
+ exists = typeLoader->fileExists(localDirectoryPath, urlToTry);
if (exists) {
#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)
// don't let function.qml confuse the use of "new Function(...)" for example.
- if (!QQml_isFileCaseCorrect(localDirectoryPath + urlsToTry[i])) {
+ if (!QQml_isFileCaseCorrect(localDirectoryPath + urlToTry)) {
exists = false;
if (errors) {
QQmlError caseError;
@@ -797,7 +797,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
#else
Q_UNUSED(errors);
#endif
- qmlUrl = url + urlsToTry[i];
+ qmlUrl = url + urlToTry;
break;
}
}
@@ -1751,6 +1751,16 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e)
addImportPath(QStringLiteral("qrc:/qt-project.org/imports"));
addImportPath(QCoreApplication::applicationDirPath());
+#if defined(Q_OS_ANDROID)
+ addImportPath(QStringLiteral("qrc:/android_rcc_bundle/qml"));
+ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_BUNDLED_LIBS_PATH"))) {
+ const QString envImportPath = qEnvironmentVariable("QT_BUNDLED_LIBS_PATH");
+ QLatin1Char pathSep(':');
+ QStringList paths = envImportPath.split(pathSep, QString::SkipEmptyParts);
+ for (int ii = paths.count() - 1; ii >= 0; --ii)
+ addPluginPath(paths.at(ii));
+ }
+#endif
}
QQmlImportDatabase::~QQmlImportDatabase()
@@ -1798,6 +1808,18 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
if (!resolvedPath.endsWith(Slash))
resolvedPath += Slash;
+#if defined(Q_OS_ANDROID)
+ if (qmldirPath.size() > 25 && qmldirPath.at(0) == QLatin1Char(':') && qmldirPath.at(1) == QLatin1Char('/') &&
+ qmldirPath.startsWith(QStringLiteral(":/android_rcc_bundle/qml/"), Qt::CaseInsensitive)) {
+ QString pluginName = qmldirPath.mid(21) + Slash + baseName;
+ auto bundledPath = resolvedPath + QLatin1String("lib") + pluginName.replace(QLatin1Char('/'), QLatin1Char('_'));
+ for (const QString &suffix : suffixes) {
+ const QString absolutePath = typeLoader->absoluteFilePath(bundledPath + suffix);
+ if (!absolutePath.isEmpty())
+ return absolutePath;
+ }
+ }
+#endif
resolvedPath += prefix + baseName;
for (const QString &suffix : suffixes) {
const QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + suffix);
@@ -1975,12 +1997,25 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths)
/*!
\internal
*/
-bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
+static bool registerPluginTypes(QObject *instance, const QString &basePath, const QString &uri,
+ const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
{
if (qmlImportTrace())
qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath;
- return QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors);
+
+ if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors))
+ return false;
+
+ if (vmaj >= 0 && !typeNamespace.isEmpty() && !QQmlMetaType::protectModule(uri, vmaj)) {
+ QQmlError error;
+ error.setDescription(
+ QString::fromLatin1("Cannot protect module %1 %2 as it was never registered")
+ .arg(uri).arg(vmaj));
+ errors->append(error);
+ return false;
+ }
+
+ return true;
}
/*!
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index ea9c2eafb5..e24b3c447c 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -235,8 +235,6 @@ private:
const QString &baseName);
bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri,
const QString &typeNamespace, int vmaj, QList<QQmlError> *errors);
- bool registerPluginTypes(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors);
void clearDirCache();
struct QmldirCache {
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index bc06226cbf..f0ef5360b0 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -43,6 +43,7 @@
#include "qqmlexpression_p.h"
#include "qqmlobjectcreator_p.h"
+#include <private/qqmlcomponent_p.h>
void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
{
@@ -60,7 +61,7 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> parentIncubator;
QQmlContextData *cctxt = forContext;
while (cctxt) {
- if (cctxt->incubator) {
+ if (!cctxt->hasExtraObject && cctxt->incubator) {
parentIncubator = cctxt->incubator;
break;
}
@@ -148,7 +149,8 @@ void QQmlIncubatorPrivate::clear()
}
enginePriv = nullptr;
if (!rootContext.isNull()) {
- rootContext->incubator = nullptr;
+ if (!rootContext->hasExtraObject)
+ rootContext->incubator = nullptr;
rootContext = nullptr;
}
@@ -296,6 +298,20 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
tresult = creator->create(subComponentToCreate, /*parent*/nullptr, &i);
if (!tresult)
errors = creator->errors;
+ else {
+ RequiredProperties& requiredProperties = creator->requiredProperties();
+ for (auto it = initialProperties.cbegin(); it != initialProperties.cend(); ++it) {
+ auto component = tresult;
+ auto name = it.key();
+ QQmlProperty prop = QQmlComponentPrivate::removePropertyFromRequired(component, name, requiredProperties);
+ if (!prop.isValid() || !prop.write(it.value())) {
+ QQmlError error{};
+ error.setUrl(compilationUnit->url());
+ error.setDescription(QLatin1String("Could not set property %1").arg(name));
+ errors.push_back(error);
+ }
+ }
+ }
enginePriv->dereferenceScarceResources();
if (watcher.hasRecursed())
@@ -312,8 +328,14 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
ddata->indestructible = true;
ddata->explicitIndestructibleSet = true;
ddata->rootObjectInCreation = false;
- if (q)
+ if (q) {
q->setInitialState(result);
+ if (!creator->requiredProperties().empty()) {
+ const auto& unsetRequiredProperties = creator->requiredProperties();
+ for (const auto& unsetRequiredProperty: unsetRequiredProperties)
+ errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
+ }
+ }
}
if (watcher.hasRecursed())
@@ -657,6 +679,36 @@ QObject *QQmlIncubator::object() const
}
/*!
+Return a list of properties which are required but haven't been set yet.
+This list can be modified, so that subclasses which implement special logic
+setInitialProperties can mark properties set there as no longer required.
+
+\sa QQmlIncubator::setInitialProperties
+\since 5.15
+*/
+RequiredProperties &QQmlIncubatorPrivate::requiredProperties()
+{
+ return creator->requiredProperties();
+}
+
+bool QQmlIncubatorPrivate::hadRequiredProperties() const
+{
+ return creator->componentHadRequiredProperties();
+}
+
+/*!
+Stores a mapping from property names to initial values with which the incubated
+component will be initialized
+
+\sa QQmlComponent::setInitialProperties
+\since 5.15
+*/
+void QQmlIncubator::setInitialProperties(const QVariantMap &initialProperties)
+{
+ d->initialProperties = initialProperties;
+}
+
+/*!
Called when the status of the incubator changes. \a status is the new status.
The default implementation does nothing.
diff --git a/src/qml/qml/qqmlincubator.h b/src/qml/qml/qqmlincubator.h
index e68f6e3c45..f075407e73 100644
--- a/src/qml/qml/qqmlincubator.h
+++ b/src/qml/qml/qqmlincubator.h
@@ -47,6 +47,9 @@ QT_BEGIN_NAMESPACE
class QQmlEngine;
+class QQmlPropertyData;
+class QVariant;
+using QVariantMap = QMap<QString, QVariant>;
class QQmlIncubatorPrivate;
class Q_QML_EXPORT QQmlIncubator
@@ -84,6 +87,8 @@ public:
QObject *object() const;
+ void setInitialProperties(const QVariantMap &initialProperties);
+
protected:
virtual void statusChanged(Status);
virtual void setInitialState(QObject *);
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index 57ec8249cb..aadb147bd5 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -61,8 +61,12 @@
QT_BEGIN_NAMESPACE
+class QQmlPropertyData;
+struct RequiredPropertyInfo;
+using RequiredProperties = QHash<QQmlPropertyData*, RequiredPropertyInfo>;
+
class QQmlIncubator;
-class QQmlIncubatorPrivate : public QQmlEnginePrivate::Incubator
+class Q_QML_PRIVATE_EXPORT QQmlIncubatorPrivate : public QQmlEnginePrivate::Incubator
{
public:
QQmlIncubatorPrivate(QQmlIncubator *q, QQmlIncubator::IncubationMode m);
@@ -97,11 +101,14 @@ public:
QIntrusiveList<QIPBase, &QIPBase::nextWaitingFor> waitingFor;
QRecursionNode recursion;
+ QVariantMap initialProperties;
void clear();
void forceCompletion(QQmlInstantiationInterrupt &i);
void incubate(QQmlInstantiationInterrupt &i);
+ RequiredProperties &requiredProperties();
+ bool hadRequiredProperties() const;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp
index 6322302422..2bfd2d5bb4 100644
--- a/src/qml/qml/qqmlinfo.cpp
+++ b/src/qml/qml/qqmlinfo.cpp
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QQmlInfo QtQml::qmlDebug(const QObject *object)
- \relates QQmlEngine
+ \relates QtQml
\since 5.9
Prints debug messages that include the file and line number for the
@@ -91,7 +91,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QQmlInfo QtQml::qmlInfo(const QObject *object)
- \relates QQmlEngine
+ \relates QtQml
Prints informational messages that include the file and line number for the
specified QML \a object.
@@ -119,7 +119,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QQmlInfo QtQml::qmlWarning(const QObject *object)
- \relates QQmlEngine
+ \relates QtQml
\since 5.9
Prints warning messages that include the file and line number for the
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 859c36e11b..10e0dfcc38 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -94,6 +94,9 @@ private:
class Q_QML_PRIVATE_EXPORT QQmlLocale
{
Q_GADGET
+ QML_NAMED_ELEMENT(Locale)
+ QML_UNCREATABLE("Locale cannot be instantiated. Use Qt.locale().")
+ QML_ADDED_IN_MINOR_VERSION(2)
public:
~QQmlLocale();
diff --git a/src/qml/qml/qqmlloggingcategory_p.h b/src/qml/qml/qqmlloggingcategory_p.h
index ee5d9af2e7..c7377528b4 100644
--- a/src/qml/qml/qqmlloggingcategory_p.h
+++ b/src/qml/qml/qqmlloggingcategory_p.h
@@ -56,6 +56,7 @@
#include <QtCore/qloggingcategory.h>
#include <QtQml/qqmlparserstatus.h>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -66,6 +67,8 @@ class QQmlLoggingCategory : public QObject, public QQmlParserStatus
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION 12)
+ QML_NAMED_ELEMENT(LoggingCategory)
+ QML_ADDED_IN_MINOR_VERSION(8)
public:
enum DefaultLogLevel {
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 2c641d3845..1a5affb0ad 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -154,7 +154,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
d->extraData.cd->propertyValueSourceCast = type.valueSourceCast;
d->extraData.cd->propertyValueInterceptorCast = type.valueInterceptorCast;
d->extraData.cd->extFunc = type.extensionObjectCreate;
- d->extraData.cd->customParser = type.customParser;
+ d->extraData.cd->customParser = reinterpret_cast<QQmlCustomParser *>(type.customParser);
d->extraData.cd->registerEnumClassesUnscoped = true;
if (type.extensionMetaObject)
@@ -342,7 +342,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType)
// NOTE: caller must hold a QMutexLocker on "data"
bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data,
- const char *uri, const QString &typeName, int majorVersion = -1)
+ const char *uri, const QString &typeName, int majorVersion)
{
if (!typeName.isEmpty()) {
if (typeName.at(0).isLower()) {
@@ -363,27 +363,16 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
if (uri && !typeName.isEmpty()) {
QString nameSpace = QString::fromUtf8(uri);
-
- if (data->typeRegistrationNamespace.isEmpty() && !nameSpace.isEmpty()) {
- // Is the target namespace protected against further registrations?
- if (data->protectedNamespaces.contains(nameSpace)) {
+ QQmlMetaTypeData::VersionedUri versionedUri;
+ versionedUri.uri = nameSpace;
+ versionedUri.majorVersion = majorVersion;
+ if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){
+ if (qqtm->isLocked()){
QString failure(QCoreApplication::translate("qmlRegisterType",
- "Cannot install %1 '%2' into protected namespace '%3'"));
- data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace));
+ "Cannot install %1 '%2' into protected module '%3' version '%4'"));
+ data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion));
return false;
}
- } else if (majorVersion >= 0) {
- QQmlMetaTypeData::VersionedUri versionedUri;
- versionedUri.uri = nameSpace;
- versionedUri.majorVersion = majorVersion;
- if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){
- if (qqtm->isLocked()){
- QString failure(QCoreApplication::translate("qmlRegisterType",
- "Cannot install %1 '%2' into protected module '%3' version '%4'"));
- data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion));
- return false;
- }
- }
}
}
@@ -477,8 +466,10 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe
bool fileImport = false;
if (*(type.uri) == '\0')
fileImport = true;
- if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri, typeName))
+ if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri,
+ typeName, type.versionMajor)) {
return QQmlType();
+ }
QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
addTypeToData(priv, data);
@@ -560,12 +551,12 @@ int QQmlMetaType::registerUnitCacheHook(
return 0;
}
-bool QQmlMetaType::protectModule(const char *uri, int majVersion)
+bool QQmlMetaType::protectModule(const QString &uri, int majVersion)
{
QQmlMetaTypeDataPtr data;
QQmlMetaTypeData::VersionedUri versionedUri;
- versionedUri.uri = QString::fromUtf8(uri);
+ versionedUri.uri = uri;
versionedUri.majorVersion = majVersion;
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) {
@@ -683,8 +674,6 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat
}
return false;
}
-
- data->protectedNamespaces.insert(uri);
} else {
// This is not an identified module - provide a warning
qWarning().nospace() << qPrintable(
@@ -698,11 +687,9 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat
= QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
}
- data->typeRegistrationNamespace = typeNamespace;
const QByteArray bytes = uri.toUtf8();
const char *moduleId = bytes.constData();
iface->registerTypes(moduleId);
- data->typeRegistrationNamespace.clear();
}
if (!failures.isEmpty()) {
@@ -739,9 +726,16 @@ QQmlType QQmlMetaType::typeForUrl(const QString &urlString,
const QUrl url = QQmlTypeLoader::normalize(QUrl(urlString));
QQmlMetaTypeDataPtr data;
- QQmlType ret(data->urlToType.value(url));
- if (ret.isValid() && ret.sourceUrl() == url)
- return ret;
+ {
+ QQmlType ret(data->urlToType.value(url));
+ if (ret.isValid() && ret.sourceUrl() == url)
+ return ret;
+ }
+ {
+ QQmlType ret(data->urlToNonFileImportType.value(url));
+ if (ret.isValid() && ret.sourceUrl() == url)
+ return ret;
+ }
const int dot = qualifiedType.indexOf(QLatin1Char('.'));
const QString typeName = dot < 0
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 6c2b0bb2a6..35d5386e1f 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -84,7 +84,7 @@ public:
static void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
static void registerModule(const char *uri, int versionMajor, int versionMinor);
- static bool protectModule(const char *uri, int majVersion);
+ static bool protectModule(const QString &uri, int majVersion);
static int typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
index 5dc0083f54..775bc8bdb4 100644
--- a/src/qml/qml/qqmlmetatypedata.cpp
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -69,6 +69,7 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
if (!types.at(i).isValid()) {
types[i] = QQmlType(priv);
priv->index = i;
+ priv->release();
return;
}
}
@@ -149,7 +150,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
bool hasCopied = false;
for (int ii = 0; ii < types.count(); ++ii) {
- QQmlType currentType = types.at(ii);
+ const QQmlType &currentType = types.at(ii);
if (!currentType.isValid())
continue;
diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
index 5239b635ce..ea796ee7c6 100644
--- a/src/qml/qml/qqmlmetatypedata_p.h
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -106,10 +106,6 @@ struct QQmlMetaTypeData
QList<QQmlPrivate::AutoParentFunction> parentFunctions;
QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit;
- QSet<QString> protectedNamespaces;
-
- QString typeRegistrationNamespace;
-
QHash<int, int> qmlLists;
QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index f89608cd5d..cf1795aafa 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -93,6 +93,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
sharedState->allJavaScriptObjects = nullptr;
sharedState->creationContext = creationContext;
sharedState->rootContext = nullptr;
+ sharedState->hadRequiredProperties = false;
if (auto profiler = QQmlEnginePrivate::get(engine)->profiler) {
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
@@ -445,6 +446,8 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
QV4::ScopedString s(scope, v4->newString(stringValue));
_vmeMetaObject->setVMEProperty(property->coreIndex(), s);
} else {
+ // ### Qt 6: Doing the conversion here where we don't know the eventual target type is rather strange
+ // and caused for instance QTBUG-78943
QVariant value = QQmlStringConverters::variantFromString(stringValue);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
@@ -783,6 +786,23 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
+ QQmlPropertyData *const property = propertyData.at(i);
+ if (property) {
+ QQmlPropertyData* targetProperty = property;
+ if (targetProperty->isAlias()) {
+ // follow alias
+ auto target = _bindingTarget;
+ QQmlPropertyIndex originalIndex(targetProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
+ QQmlPropertyIndex propIndex;
+ QQmlPropertyPrivate::findAliasTarget(target, originalIndex, &target, &propIndex);
+ QQmlData *data = QQmlData::get(target);
+ Q_ASSERT(data && data->propertyCache);
+ targetProperty = data->propertyCache->property(propIndex.coreIndex());
+ }
+ sharedState->requiredProperties.remove(targetProperty);
+ }
+
+
if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding)
continue;
@@ -794,8 +814,6 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
continue;
}
- const QQmlPropertyData *property = propertyData.at(i);
-
if (property && property->isQList()) {
if (property->coreIndex() != currentListPropertyIndex) {
void *argv[1] = { (void*)&_currentList };
@@ -1504,10 +1522,43 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings)
_ddata->deferData(_compiledObjectIndex, compilationUnit, context);
+ for (int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) {
+ const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex;
+ QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
+ if (property->isRequired) {
+ sharedState->hadRequiredProperties = true;
+ sharedState->requiredProperties.insert(propertyData,
+ RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex), compilationUnit->finalUrl(), property->location, {}});
+ }
+ }
+
if (_compiledObject->nFunctions > 0)
setupFunctions();
setupBindings();
+ for (int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
+ const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
+ const auto originalAlias = alias;
+ while (alias->aliasToLocalAlias)
+ alias = _compiledObject->aliasesBegin() + alias->localAliasIndex;
+ Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+ if (!context->idValues->wasSet())
+ continue;
+ QObject *target = context->idValues[alias->targetObjectId].data();
+ if (!target)
+ continue;
+ QQmlData *targetDData = QQmlData::get(target, /*create*/false);
+ if (!targetDData)
+ continue;
+ int coreIndex = QQmlPropertyIndex::fromEncoded(alias->encodedMetaPropertyIndex).coreIndex();
+ QQmlPropertyData *const targetProperty = targetDData->propertyCache->property(coreIndex);
+ if (!targetProperty)
+ continue;
+ auto it = sharedState->requiredProperties.find(targetProperty);
+ if (it != sharedState->requiredProperties.end())
+ it->aliasesToRequired.push_back(AliasToRequiredInfo {compilationUnit->stringAt(originalAlias->nameIndex), compilationUnit->finalUrl()});
+ }
+
qSwap(_vmeMetaObject, vmeMetaObject);
qSwap(_bindingTarget, bindingTarget);
qSwap(_ddata, declarativeData);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index ecdbcc56dd..59e236c855 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -66,6 +66,28 @@ class QQmlAbstractBinding;
class QQmlInstantiationInterrupt;
class QQmlIncubatorPrivate;
+struct AliasToRequiredInfo {
+ QString propertyName;
+ QUrl fileUrl;
+};
+
+/*!
+\internal
+This struct contains information solely used for displaying error messages
+\variable aliasesToRequired allows us to give the user a way to know which (aliasing) properties
+can be set to set the required property
+\sa QQmlComponentPrivate::unsetRequiredPropertyToQQmlError
+*/
+struct RequiredPropertyInfo
+{
+ QString propertyName;
+ QUrl fileUrl;
+ QV4::CompiledData::Location location;
+ QVector<AliasToRequiredInfo> aliasesToRequired;
+};
+
+using RequiredProperties = QHash<QQmlPropertyData*, RequiredPropertyInfo>;
+
struct QQmlObjectCreatorSharedState : public QSharedData
{
QQmlContextData *rootContext;
@@ -78,6 +100,8 @@ struct QQmlObjectCreatorSharedState : public QSharedData
QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
QQmlVmeProfiler profiler;
QRecursionNode recursionNode;
+ RequiredProperties requiredProperties;
+ bool hadRequiredProperties;
};
class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
@@ -102,6 +126,9 @@ public:
QQmlContextData *parentContextData() const { return parentContext.contextData(); }
QFiniteStack<QPointer<QObject> > &allCreatedObjects() { return sharedState->allCreatedObjects; }
+ RequiredProperties &requiredProperties() {return sharedState->requiredProperties;}
+ bool componentHadRequiredProperties() const {return sharedState->hadRequiredProperties;}
+
private:
QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index e6dd5e0b16..27dac71571 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -52,17 +52,43 @@
//
#include <functional>
+#include <type_traits>
#include <QtQml/qtqmlglobal.h>
+#include <QtQml/qqmlparserstatus.h>
+#include <QtQml/qqmllist.h>
+#include <QtQml/qqmlpropertyvaluesource.h>
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
+#include <QPointer>
+
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+
+#define QML_GETTYPENAMES \
+ const char *className = T::staticMetaObject.className(); \
+ const int nameLen = int(strlen(className)); \
+ QVarLengthArray<char,48> pointerName(nameLen+2); \
+ memcpy(pointerName.data(), className, size_t(nameLen)); \
+ pointerName[nameLen] = '*'; \
+ pointerName[nameLen+1] = '\0'; \
+ const int listLen = int(strlen("QQmlListProperty<")); \
+ QVarLengthArray<char,64> listName(listLen + nameLen + 2); \
+ memcpy(listName.data(), "QQmlListProperty<", size_t(listLen)); \
+ memcpy(listName.data()+listLen, className, size_t(nameLen)); \
+ listName[listLen+nameLen] = '>'; \
+ listName[listLen+nameLen+1] = '\0';
QT_BEGIN_NAMESPACE
+class QQmlPropertyValueInterceptor;
+
namespace QQmlPrivate {
struct CachedQmlUnit;
+template<typename A>
+using QQmlAttachedPropertiesFunc = A *(*)(QObject *);
}
namespace QV4 {
@@ -77,7 +103,7 @@ struct Document;
typedef void (*IRLoaderFunction)(Document *, const QQmlPrivate::CachedQmlUnit *);
}
-typedef QObject *(*QQmlAttachedPropertiesFunc)(QObject *);
+using QQmlAttachedPropertiesFunc = QQmlPrivate::QQmlAttachedPropertiesFunc<QObject>;
inline uint qHash(QQmlAttachedPropertiesFunc func, uint seed = 0)
{
@@ -98,6 +124,13 @@ class QJSValue;
class QJSEngine;
class QQmlEngine;
class QQmlCustomParser;
+
+template<class T>
+QQmlCustomParser *qmlCreateCustomParser()
+{
+ return nullptr;
+}
+
namespace QQmlPrivate
{
void Q_QML_EXPORT qdeclarativeelement_destructor(QObject *);
@@ -123,11 +156,62 @@ namespace QQmlPrivate
};
template<typename T>
+ constexpr bool isConstructible()
+ {
+ return std::is_default_constructible<T>::value && std::is_base_of<QObject, T>::value;
+ }
+
+ template<typename T>
void createInto(void *memory) { new (memory) QQmlElement<T>; }
template<typename T>
+ QObject *createSingletonInstance(QQmlEngine *, QJSEngine *) { return new T; }
+
+ template<typename T>
QObject *createParent(QObject *p) { return new T(p); }
+ using CreateIntoFunction = void (*)(void *);
+ using CreateSingletonFunction = QObject *(*)(QQmlEngine *, QJSEngine *);
+ using CreateParentFunction = QObject *(*)(QObject *);
+
+ template<typename T, bool Constructible = isConstructible<T>()>
+ struct Constructors;
+
+ template<typename T>
+ struct Constructors<T, true>
+ {
+ static constexpr CreateIntoFunction createInto
+ = QQmlPrivate::createInto<T>;
+ static constexpr CreateSingletonFunction createSingletonInstance
+ = QQmlPrivate::createSingletonInstance<T>;
+ };
+
+ template<typename T>
+ struct Constructors<T, false>
+ {
+ static constexpr CreateIntoFunction createInto = nullptr;
+ static constexpr CreateSingletonFunction createSingletonInstance = nullptr;
+ };
+
+ template<typename T, bool IsVoid = std::is_void<T>::value>
+ struct ExtendedType;
+
+ // void means "not an extended type"
+ template<typename T>
+ struct ExtendedType<T, true>
+ {
+ static constexpr const CreateParentFunction createParent = nullptr;
+ static constexpr const QMetaObject *staticMetaObject = nullptr;
+ };
+
+ // If it's not void, we actually want an error if the ctor or the metaobject is missing.
+ template<typename T>
+ struct ExtendedType<T, false>
+ {
+ static constexpr const CreateParentFunction createParent = QQmlPrivate::createParent<T>;
+ static constexpr const QMetaObject *staticMetaObject = &T::staticMetaObject;
+ };
+
template<class From, class To, int N>
struct StaticCastSelectorClass
{
@@ -155,66 +239,103 @@ namespace QQmlPrivate
}
};
- template <typename T>
- struct has_attachedPropertiesMember
+ template<typename...>
+ using QmlVoidT = void;
+
+ // You can prevent subclasses from using the same attached type by specialzing this.
+ // This is reserved for internal types, though.
+ template<class T, class A>
+ struct OverridableAttachedType
{
- static bool const value = QQmlTypeInfo<T>::hasAttachedProperties;
+ using Type = A;
};
- template <typename T, bool hasMember>
- class has_attachedPropertiesMethod
+ template<class T, class = QmlVoidT<>, bool OldStyle = QQmlTypeInfo<T>::hasAttachedProperties>
+ struct QmlAttached
{
- public:
- typedef int yes_type;
- typedef char no_type;
-
- template<typename ReturnType>
- static yes_type checkType(ReturnType *(*)(QObject *));
- static no_type checkType(...);
-
- static bool const value = sizeof(checkType(&T::qmlAttachedProperties)) == sizeof(yes_type);
+ using Type = void;
+ using Func = QQmlAttachedPropertiesFunc<QObject>;
+ static const QMetaObject *staticMetaObject() { return nullptr; }
+ static Func attachedPropertiesFunc() { return nullptr; }
};
- template <typename T>
- class has_attachedPropertiesMethod<T, false>
+ // Defined inline via QML_ATTACHED
+ template<class T>
+ struct QmlAttached<T, QmlVoidT<typename OverridableAttachedType<T, typename T::QmlAttachedType>::Type>, false>
{
- public:
- static bool const value = false;
+ // Normal attached properties
+ template <typename Parent, typename Attached>
+ struct Properties
+ {
+ using Func = QQmlAttachedPropertiesFunc<Attached>;
+ static const QMetaObject *staticMetaObject() { return &Attached::staticMetaObject; }
+ static Func attachedPropertiesFunc() { return Parent::qmlAttachedProperties; }
+ };
+
+ // Disabled via OverridableAttachedType
+ template<typename Parent>
+ struct Properties<Parent, void>
+ {
+ using Func = QQmlAttachedPropertiesFunc<QObject>;
+ static const QMetaObject *staticMetaObject() { return nullptr; };
+ static Func attachedPropertiesFunc() { return nullptr; };
+ };
+
+ using Type = typename OverridableAttachedType<T, typename T::QmlAttachedType>::Type;
+ using Func = typename Properties<T, Type>::Func;
+
+ static const QMetaObject *staticMetaObject()
+ {
+ return Properties<T, Type>::staticMetaObject();
+ }
+
+ static Func attachedPropertiesFunc()
+ {
+ return Properties<T, Type>::attachedPropertiesFunc();
+ }
};
- template<typename T, int N>
- class AttachedPropertySelector
+ // Separately defined via QQmlTypeInfo
+ template<class T>
+ struct QmlAttached<T, QmlVoidT<decltype(T::qmlAttachedProperties)>, true>
{
- public:
- static inline QQmlAttachedPropertiesFunc func() { return nullptr; }
- static inline const QMetaObject *metaObject() { return nullptr; }
+ using Type = typename std::remove_pointer<decltype(T::qmlAttachedProperties(nullptr))>::type;
+ using Func = QQmlAttachedPropertiesFunc<Type>;
+
+ static const QMetaObject *staticMetaObject() { return &Type::staticMetaObject; }
+ static Func attachedPropertiesFunc() { return T::qmlAttachedProperties; }
};
- template<typename T>
- class AttachedPropertySelector<T, 1>
+
+ // This is necessary because both the type containing a default template parameter and the type
+ // instantiating the template need to have access to the default template parameter type. In
+ // this case that's T::QmlAttachedType. The QML_FOREIGN macro needs to befriend specific other
+ // types. Therefore we need some kind of "accessor". Because of compiler bugs in gcc and clang,
+ // we cannot befriend attachedPropertiesFunc() directly. Wrapping the actual access into another
+ // struct "fixes" that. For convenience we still want the free standing functions in addition.
+ template<class T>
+ struct QmlAttachedAccessor
{
- template<typename ReturnType>
- static inline const QMetaObject *attachedPropertiesMetaObject(ReturnType *(*)(QObject *)) {
- return &ReturnType::staticMetaObject;
- }
- public:
- static inline QQmlAttachedPropertiesFunc func() {
- return QQmlAttachedPropertiesFunc(&T::qmlAttachedProperties);
+ static QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunc()
+ {
+ return QQmlAttachedPropertiesFunc<QObject>(QmlAttached<T>::attachedPropertiesFunc());
}
- static inline const QMetaObject *metaObject() {
- return attachedPropertiesMetaObject(&T::qmlAttachedProperties);
+
+ static const QMetaObject *staticMetaObject()
+ {
+ return QmlAttached<T>::staticMetaObject();
}
};
template<typename T>
- inline QQmlAttachedPropertiesFunc attachedPropertiesFunc()
+ inline QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunc()
{
- return AttachedPropertySelector<T, has_attachedPropertiesMethod<T, has_attachedPropertiesMember<T>::value>::value>::func();
+ return QmlAttachedAccessor<T>::attachedPropertiesFunc();
}
template<typename T>
inline const QMetaObject *attachedPropertiesMetaObject()
{
- return AttachedPropertySelector<T, has_attachedPropertiesMethod<T, has_attachedPropertiesMember<T>::value>::value>::metaObject();
+ return QmlAttachedAccessor<T>::staticMetaObject();
}
enum AutoParentResult { Parented, IncompatibleObject, IncompatibleParent };
@@ -235,7 +356,7 @@ namespace QQmlPrivate
const char *elementName;
const QMetaObject *metaObject;
- QQmlAttachedPropertiesFunc attachedPropertiesFunction;
+ QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunction;
const QMetaObject *attachedPropertiesMetaObject;
int parserStatusCast;
@@ -246,10 +367,38 @@ namespace QQmlPrivate
const QMetaObject *extensionMetaObject;
QQmlCustomParser *customParser;
+
int revision;
// If this is extended ensure "version" is bumped!!!
};
+ struct RegisterTypeAndRevisions {
+ int version;
+
+ int typeId;
+ int listId;
+ int objectSize;
+ void (*create)(void *);
+
+ const char *uri;
+ int versionMajor;
+
+ const QMetaObject *metaObject;
+ const QMetaObject *classInfoMetaObject;
+
+ QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunction;
+ const QMetaObject *attachedPropertiesMetaObject;
+
+ int parserStatusCast;
+ int valueSourceCast;
+ int valueInterceptorCast;
+
+ QObject *(*extensionObjectCreate)(QObject *);
+ const QMetaObject *extensionMetaObject;
+
+ QQmlCustomParser *(*customParserFactory)();
+ };
+
struct RegisterInterface {
int version;
@@ -282,6 +431,19 @@ namespace QQmlPrivate
// If this is extended ensure "version" is bumped!!!
};
+ struct RegisterSingletonTypeAndRevisions {
+ int version;
+ const char *uri;
+ int versionMajor;
+
+ QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *);
+ const QMetaObject *instanceMetaObject;
+ const QMetaObject *classInfoMetaObject;
+
+ int typeId;
+ std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3
+ };
+
struct RegisterCompositeType {
QUrl url;
const char *uri;
@@ -317,7 +479,9 @@ namespace QQmlPrivate
SingletonRegistration = 3,
CompositeRegistration = 4,
CompositeSingletonRegistration = 5,
- QmlUnitCacheHookRegistration = 6
+ QmlUnitCacheHookRegistration = 6,
+ TypeAndRevisionsRegistration = 7,
+ SingletonAndRevisionsRegistration = 8
};
int Q_QML_EXPORT qmlregister(RegistrationType, void *);
@@ -326,10 +490,154 @@ namespace QQmlPrivate
{
QObject *operator()(QQmlEngine *, QJSEngine *);
- QObject *m_object;
+ QPointer<QObject> m_object;
bool alreadyCalled = false;
};
-}
+
+ static int indexOfOwnClassInfo(const QMetaObject *metaObject, const char *key)
+ {
+ if (!metaObject || !key)
+ return -1;
+
+ const int offset = metaObject->classInfoOffset();
+ for (int i = metaObject->classInfoCount() + offset - 1; i >= offset; --i)
+ if (qstrcmp(key, metaObject->classInfo(i).name()) == 0) {
+ return i;
+ }
+ return -1;
+ }
+
+ inline const char *classInfo(const QMetaObject *metaObject, const char *key)
+ {
+ return metaObject->classInfo(indexOfOwnClassInfo(metaObject, key)).value();
+ }
+
+ inline int intClassInfo(const QMetaObject *metaObject, const char *key, int defaultValue = 0)
+ {
+ const int index = indexOfOwnClassInfo(metaObject, key);
+ return (index == -1) ? defaultValue
+ : QByteArray(metaObject->classInfo(index).value()).toInt();
+ }
+
+ inline bool boolClassInfo(const QMetaObject *metaObject, const char *key,
+ bool defaultValue = false)
+ {
+ const int index = indexOfOwnClassInfo(metaObject, key);
+ return (index == -1) ? defaultValue
+ : (QByteArray(metaObject->classInfo(index).value()) == "true");
+ }
+
+ inline const char *classElementName(const QMetaObject *metaObject)
+ {
+ const char *elementName = classInfo(metaObject, "QML.Element");
+ if (qstrcmp(elementName, "auto") == 0)
+ return metaObject->className();
+ if (qstrcmp(elementName, "anonymous") == 0)
+ return nullptr;
+
+ if (!elementName || elementName[0] < 'A' || elementName[0] > 'Z') {
+ qWarning() << "Missing or unusable QML.Element class info \"" << elementName << "\""
+ << "for" << metaObject->className();
+ }
+
+ return elementName;
+ }
+
+ template<class T, class = QmlVoidT<>>
+ struct QmlExtended
+ {
+ using Type = void;
+ };
+
+ template<class T>
+ struct QmlExtended<T, QmlVoidT<typename T::QmlExtendedType>>
+ {
+ using Type = typename T::QmlExtendedType;
+ };
+
+ template<class T, class = QmlVoidT<>>
+ struct QmlResolved
+ {
+ using Type = T;
+ };
+
+ template<class T>
+ struct QmlResolved<T, QmlVoidT<typename T::QmlForeignType>>
+ {
+ using Type = typename T::QmlForeignType;
+ };
+
+ template<class T, class = QmlVoidT<>>
+ struct QmlSingleton
+ {
+ static constexpr bool Value = false;
+ };
+
+ template<class T>
+ struct QmlSingleton<T, QmlVoidT<typename T::QmlIsSingleton>>
+ {
+ static constexpr bool Value = bool(T::QmlIsSingleton::yes);
+ };
+
+ template<typename T>
+ void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor,
+ const QMetaObject *classInfoMetaObject)
+ {
+ QML_GETTYPENAMES
+
+ RegisterSingletonTypeAndRevisions api = {
+ 0,
+
+ uri,
+ versionMajor,
+
+ nullptr,
+
+ &T::staticMetaObject,
+ classInfoMetaObject,
+
+ qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+ Constructors<T>::createSingletonInstance
+ };
+
+ qmlregister(SingletonAndRevisionsRegistration, &api);
+ }
+
+ template<typename T, typename E>
+ void qmlRegisterTypeAndRevisions(const char *uri, int versionMajor,
+ const QMetaObject *classInfoMetaObject)
+ {
+ QML_GETTYPENAMES
+
+ RegisterTypeAndRevisions type = {
+ 0,
+ qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+ qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ int(sizeof(T)),
+ Constructors<T>::createInto,
+
+ uri,
+ versionMajor,
+
+ &T::staticMetaObject,
+ classInfoMetaObject,
+
+ attachedPropertiesFunc<T>(),
+ attachedPropertiesMetaObject<T>(),
+
+ StaticCastSelector<T, QQmlParserStatus>::cast(),
+ StaticCastSelector<T, QQmlPropertyValueSource>::cast(),
+ StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(),
+
+ ExtendedType<E>::createParent,
+ ExtendedType<E>::staticMetaObject,
+
+ &qmlCreateCustomParser<T>
+ };
+
+ qmlregister(TypeAndRevisionsRegistration, &type);
+ }
+} // namespace QQmlPrivate
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 5f57e0eca1..eff3e94fbd 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -885,7 +885,7 @@ void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags
QQmlData *data = QQmlData::get(object, true);
if (data->propertyCache) {
QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
- Q_ASSERT(propertyData && !propertyData->isAlias());
+ Q_ASSERT(propertyData);
}
#endif
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index 9c7a69d571..39778aa328 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -152,9 +152,18 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil
template <typename ObjectContainer>
inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context)
{
+ auto isAddressable = [](const QUrl &url) {
+ const QString fileName = url.fileName();
+ return !fileName.isEmpty() && fileName.front().isUpper();
+ };
+
const CompiledObject *obj = objectContainer->objectAt(objectIndex);
+ bool needVMEMetaObject = obj->propertyCount() != 0 || obj->aliasCount() != 0
+ || obj->signalCount() != 0 || obj->functionCount() != 0 || obj->enumCount() != 0
+ || (((obj->flags & QV4::CompiledData::Object::IsComponent)
+ || (objectIndex == 0 && isAddressable(objectContainer->url())))
+ && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType);
- bool needVMEMetaObject = obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0 || obj->enumCount() != 0;
if (!needVMEMetaObject) {
auto binding = obj->bindingsBegin();
auto end = obj->bindingsEnd();
@@ -256,17 +265,8 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
Q_ASSERT(typeRef);
QQmlType qmltype = typeRef->type;
if (!qmltype.isValid()) {
- QString propertyName = stringAt(context.instantiatingBinding->propertyNameIndex);
- if (imports->resolveType(propertyName, &qmltype, nullptr, nullptr, nullptr)) {
- if (qmltype.isComposite()) {
- QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
-
- auto compilationUnit = tdata->compilationUnit();
- qmltype = QQmlMetaType::qmlType(compilationUnit->metaTypeId);
- }
- }
+ imports->resolveType(stringAt(context.instantiatingBinding->propertyNameIndex),
+ &qmltype, nullptr, nullptr, nullptr);
}
const QMetaObject *attachedMo = qmltype.attachedPropertiesType(enginePrivate);
@@ -585,13 +585,13 @@ public:
QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer);
- void appendAliasPropertiesToMetaObjects();
+ void appendAliasPropertiesToMetaObjects(QQmlEnginePrivate *enginePriv);
- QQmlJS::DiagnosticMessage appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex);
+ QQmlJS::DiagnosticMessage appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv);
private:
- void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex);
- QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags);
+ void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv);
+ QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv);
void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const;
@@ -610,7 +610,7 @@ inline QQmlPropertyCacheAliasCreator<ObjectContainer>::QQmlPropertyCacheAliasCre
}
template <typename ObjectContainer>
-inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesToMetaObjects()
+inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesToMetaObjects(QQmlEnginePrivate *enginePriv)
{
// skip the root object (index 0) as that one does not have a first object index originating
// from a binding.
@@ -620,15 +620,15 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertie
continue;
const auto rootBinding = component.bindingsBegin();
- appendAliasPropertiesInMetaObjectsWithinComponent(component, rootBinding->value.objectIndex);
+ appendAliasPropertiesInMetaObjectsWithinComponent(component, rootBinding->value.objectIndex, enginePriv);
}
const int rootObjectIndex = 0;
- appendAliasPropertiesInMetaObjectsWithinComponent(*objectContainer->objectAt(rootObjectIndex), rootObjectIndex);
+ appendAliasPropertiesInMetaObjectsWithinComponent(*objectContainer->objectAt(rootObjectIndex), rootObjectIndex, enginePriv);
}
template <typename ObjectContainer>
-inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex)
+inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv)
{
QVector<int> objectsWithAliases;
collectObjectsWithAliasesRecursively(firstObjectIndex, &objectsWithAliases);
@@ -668,7 +668,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertie
const CompiledObject &object = *objectContainer->objectAt(objectIndex);
if (allAliasTargetsExist(object)) {
- appendAliasesToPropertyCache(component, objectIndex);
+ appendAliasesToPropertyCache(component, objectIndex, enginePriv);
} else {
pendingObjects.append(objectIndex);
}
@@ -702,9 +702,8 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl
}
template <typename ObjectContainer>
-inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(
- const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion,
- QQmlPropertyData::Flags *propertyFlags)
+inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion,
+ QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv)
{
*type = 0;
bool writable = false;
@@ -736,7 +735,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>:
lastAlias = targetAlias;
} while (lastAlias->aliasToLocalAlias);
- return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags);
+ return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags, enginePriv);
}
const int targetObjectIndex = objectForId(component, alias.targetObjectId);
@@ -768,29 +767,46 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>:
QQmlPropertyCache *targetCache = propertyCaches->at(targetObjectIndex);
Q_ASSERT(targetCache);
+
QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
Q_ASSERT(targetProperty);
- *type = targetProperty->propType();
+ // for deep aliases, valueTypeIndex is always set
+ if (!QQmlValueTypeFactory::isValueType(targetProperty->propType()) && valueTypeIndex != -1) {
+ // deep alias property
+ *type = targetProperty->propType();
+ targetCache = enginePriv->propertyCacheForType(*type);
+ Q_ASSERT(targetCache);
+ targetProperty = targetCache->property(valueTypeIndex);
- writable = targetProperty->isWritable();
- resettable = targetProperty->isResettable();
- if (valueTypeIndex != -1) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(*type);
- if (valueTypeMetaObject->property(valueTypeIndex).isEnumType())
- *type = QVariant::Int;
- else
- *type = valueTypeMetaObject->property(valueTypeIndex).userType();
+ *type = targetProperty->propType();
+ writable = targetProperty->isWritable();
+ resettable = targetProperty->isResettable();
+
} else {
- if (targetProperty->isEnum()) {
- *type = QVariant::Int;
+ // value type or primitive type or enum
+ *type = targetProperty->propType();
+
+ writable = targetProperty->isWritable();
+ resettable = targetProperty->isResettable();
+
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(*type);
+ if (valueTypeMetaObject->property(valueTypeIndex).isEnumType())
+ *type = QVariant::Int;
+ else
+ *type = valueTypeMetaObject->property(valueTypeIndex).userType();
} else {
- // Copy type flags
- propertyFlags->copyPropertyTypeFlags(targetProperty->flags());
+ if (targetProperty->isEnum()) {
+ *type = QVariant::Int;
+ } else {
+ // Copy type flags
+ propertyFlags->copyPropertyTypeFlags(targetProperty->flags());
- if (targetProperty->isVarProperty())
- propertyFlags->type = QQmlPropertyData::Flags::QVariantType;
+ if (targetProperty->isVarProperty())
+ propertyFlags->type = QQmlPropertyData::Flags::QVariantType;
+ }
}
}
}
@@ -802,7 +818,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>:
template <typename ObjectContainer>
inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache(
- const CompiledObject &component, int objectIndex)
+ const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv)
{
const CompiledObject &object = *objectContainer->objectAt(objectIndex);
if (!object.aliasCount())
@@ -823,7 +839,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>:
int type = 0;
int minorVersion = 0;
QQmlPropertyData::Flags propertyFlags;
- QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags);
+ QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags, enginePriv);
if (error.isValid())
return error;
diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp
index 7dbcbe986b..d7361ea2c6 100644
--- a/src/qml/qml/qqmlpropertyvalidator.cpp
+++ b/src/qml/qml/qqmlpropertyvalidator.cpp
@@ -49,6 +49,19 @@
QT_BEGIN_NAMESPACE
+static bool isPrimitiveType(int typeId)
+{
+ switch (typeId) {
+#define HANDLE_PRIMITIVE(Type, id, T) \
+ case QMetaType::Type:
+QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(HANDLE_PRIMITIVE);
+#undef HANDLE_PRIMITIVE
+ return true;
+ default:
+ return false;
+ }
+}
+
QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit)
: enginePrivate(enginePrivate)
, compilationUnit(compilationUnit)
@@ -281,11 +294,21 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject(
return recordError(binding->location, tr("Invalid grouped property access"));
}
} else {
- if (!enginePrivate->propertyCacheForType(pd->propType())) {
+ const int typeId = pd->propType();
+ if (isPrimitiveType(typeId)) {
+ return recordError(
+ binding->location,
+ tr("Invalid grouped property access: Property \"%1\" with primitive type \"%2\".")
+ .arg(name)
+ .arg(QString::fromLatin1(QMetaType::typeName(typeId)))
+ );
+ }
+
+ if (!enginePrivate->propertyCacheForType(typeId)) {
return recordError(binding->location,
tr("Invalid grouped property access: Property \"%1\" with type \"%2\", which is not a value type")
.arg(name)
- .arg(QString::fromLatin1(QMetaType::typeName(pd->propType())))
+ .arg(QString::fromLatin1(QMetaType::typeName(typeId)))
);
}
}
@@ -679,15 +702,21 @@ QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPrope
return noError;
}
- if (QQmlMetaType::isInterface(property->propType())) {
+ const int propType = property->propType();
+ const auto rhsType = [&]() {
+ return stringAt(compilationUnit->objectAt(binding->value.objectIndex)
+ ->inheritedTypeNameIndex);
+ };
+
+ if (QQmlMetaType::isInterface(propType)) {
// Can only check at instantiation time if the created sub-object successfully casts to the
// target interface.
return noError;
- } else if (property->propType() == QMetaType::QVariant || property->propType() == qMetaTypeId<QJSValue>()) {
+ } else if (propType == QMetaType::QVariant || propType == qMetaTypeId<QJSValue>()) {
// We can convert everything to QVariant :)
return noError;
} else if (property->isQList()) {
- const int listType = enginePrivate->listType(property->propType());
+ const int listType = enginePrivate->listType(propType);
if (!QQmlMetaType::isInterface(listType)) {
QQmlPropertyCache *source = propertyCaches.at(binding->value.objectIndex);
if (!canCoerce(listType, source)) {
@@ -697,19 +726,23 @@ QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPrope
return noError;
} else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
return noError;
- } else if (QQmlValueTypeFactory::isValueType(property->propType())) {
- auto typeName = QMetaType::typeName(property->propType());
+ } else if (isPrimitiveType(propType)) {
+ auto typeName = QString::fromUtf8(QMetaType::typeName(propType));
+ return qQmlCompileError(binding->location, tr("Can not assign value of type \"%1\" to property \"%2\", expecting \"%3\"")
+ .arg(rhsType())
+ .arg(propertyName)
+ .arg(typeName));
+ } else if (QQmlValueTypeFactory::isValueType(propType)) {
return qQmlCompileError(binding->location, tr("Can not assign value of type \"%1\" to property \"%2\", expecting an object")
- .arg(typeName ? QString::fromLatin1(typeName) : QString::fromLatin1("<unknown type>"))
- .arg(propertyName));
- } else if (property->propType() == qMetaTypeId<QQmlScriptString>()) {
+ .arg(rhsType()).arg(propertyName));
+ } else if (propType == qMetaTypeId<QQmlScriptString>()) {
return qQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected"));
} else {
// We want to use the raw metaObject here as the raw metaobject is the
// actual property type before we applied any extensions that might
// effect the properties on the type, but don't effect assignability
// Using -1 for the minor version ensures that we get the raw metaObject.
- QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType(), -1);
+ QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(propType, -1);
if (propertyMetaObject) {
// Will be true if the assigned type inherits propertyMetaObject
@@ -723,11 +756,11 @@ QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPrope
if (!isAssignable) {
return qQmlCompileError(binding->valueLocation, tr("Cannot assign object of type \"%1\" to property of type \"%2\" as the former is neither the same as the latter nor a sub-class of it.")
- .arg(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex)).arg(QLatin1String(QMetaType::typeName(property->propType()))));
+ .arg(rhsType()).arg(QLatin1String(QMetaType::typeName(propType))));
}
} else {
return qQmlCompileError(binding->valueLocation, tr("Cannot assign to property of unknown type \"%1\".")
- .arg(QLatin1String(QMetaType::typeName(property->propType()))));
+ .arg(QLatin1String(QMetaType::typeName(propType))));
}
}
diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp
index 69b26894a8..6ac30d3ab5 100644
--- a/src/qml/qml/qqmlscriptblob.cpp
+++ b/src/qml/qml/qqmlscriptblob.cpp
@@ -177,7 +177,7 @@ void QQmlScriptBlob::done()
}
if (!m_isModule) {
- m_scriptData->typeNameCache = new QQmlTypeNameCache(m_importCache);
+ m_scriptData->typeNameCache.adopt(new QQmlTypeNameCache(m_importCache));
QSet<QString> ns;
@@ -195,7 +195,7 @@ void QQmlScriptBlob::done()
m_scriptData->typeNameCache->add(script.qualifier, scriptIndex, script.nameSpace);
}
- m_importCache.populateCache(m_scriptData->typeNameCache);
+ m_importCache.populateCache(m_scriptData->typeNameCache.data());
}
m_scripts.clear();
}
diff --git a/src/qml/qml/qqmlscriptdata.cpp b/src/qml/qml/qqmlscriptdata.cpp
index 0725f40d2a..ae268ca904 100644
--- a/src/qml/qml/qqmlscriptdata.cpp
+++ b/src/qml/qml/qqmlscriptdata.cpp
@@ -156,11 +156,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
void QQmlScriptData::clear()
{
- if (typeNameCache) {
- typeNameCache->release();
- typeNameCache = nullptr;
- }
-
+ typeNameCache = nullptr;
scripts.clear();
// An addref() was made when the QQmlCleanup was added to the engine.
diff --git a/src/qml/qml/qqmlscriptdata_p.h b/src/qml/qml/qqmlscriptdata_p.h
index 273ba3691f..80b65b699c 100644
--- a/src/qml/qml/qqmlscriptdata_p.h
+++ b/src/qml/qml/qqmlscriptdata_p.h
@@ -82,7 +82,7 @@ private:
public:
QUrl url;
QString urlString;
- QQmlTypeNameCache *typeNameCache;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
QVector<QQmlRefPointer<QQmlScriptBlob>> scripts;
QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index 2a6831d898..874bcd4bca 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -91,6 +91,8 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
QQmlTypePrivate::~QQmlTypePrivate()
{
qDeleteAll(scopedEnums);
+ for (const auto &metaObject : metaObjects)
+ free(metaObject.metaObject);
switch (regType) {
case QQmlType::CppType:
delete extraData.cd->customParser;
@@ -154,27 +156,10 @@ bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, in
return module == d->module && vmajor == d->version_maj && vminor >= d->version_min;
}
-// returns the nearest _registered_ super class
-QQmlType QQmlType::superType() const
-{
- if (!d)
- return QQmlType();
- if (!d->haveSuperType && d->baseMetaObject) {
- const QMetaObject *mo = d->baseMetaObject->superClass();
- while (mo && !d->superType.isValid()) {
- d->superType = QQmlMetaType::qmlType(mo, d->module, d->version_maj, d->version_min);
- mo = mo->superClass();
- }
- d->haveSuperType = true;
- }
-
- return d->superType;
-}
-
-QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
+QQmlType QQmlTypePrivate::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
{
Q_ASSERT(isComposite());
- if (!engine || !d)
+ if (!engine)
return QQmlType();
QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
@@ -184,7 +169,7 @@ QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
return QQmlMetaType::qmlType(mo);
}
-QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) const
+QQmlPropertyCache *QQmlTypePrivate::compositePropertyCache(QQmlEnginePrivate *engine) const
{
// similar logic to resolveCompositeBaseType
Q_ASSERT(isComposite());
@@ -279,24 +264,30 @@ void QQmlTypePrivate::init() const
lock.unlock();
}
-void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const
+void QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const
{
- if ((isEnumFromBaseSetup || !baseMetaObject)
- && (isEnumFromCacheSetup || !cache)) {
+ const QQmlPropertyCache *cache = (!isEnumFromCacheSetup && isComposite())
+ ? compositePropertyCache(engine)
+ : nullptr;
+
+ const QMetaObject *metaObject = !isEnumFromCacheSetup
+ ? baseMetaObject // beware: It could be a singleton type without metaobject
+ : nullptr;
+
+ if (!cache && !metaObject)
return;
- }
init();
QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
- if (!isEnumFromCacheSetup && cache) {
+ if (cache) {
insertEnumsFromPropertyCache(cache);
isEnumFromCacheSetup = true;
}
- if (!isEnumFromBaseSetup && baseMetaObject) { // could be singleton type without metaobject
- insertEnums(baseMetaObject);
+ if (metaObject) {
+ insertEnums(metaObject);
isEnumFromBaseSetup = true;
}
}
@@ -404,7 +395,7 @@ void QQmlTypePrivate::createEnumConflictReport(const QMetaObject *metaObject, co
qWarning().noquote() << QLatin1String("Possible conflicting items:");
// find items with conflicting key
- for (const auto i : enumInfoList) {
+ for (const auto &i : qAsConst(enumInfoList)) {
if (i.enumKey == conflictingKey)
qWarning().noquote().nospace() << " " << i.metaObjectName << "." << i.enumName << "." << i.enumKey << " from scope "
<< i.metaEnumScope << " injected by " << i.path.join(QLatin1String("->"));
@@ -565,7 +556,7 @@ bool QQmlType::isInterface() const
bool QQmlType::isComposite() const
{
- return d && (d->regType == CompositeType || d->regType == CompositeSingletonType);
+ return d && d->isComposite();
}
bool QQmlType::isCompositeSingleton() const
@@ -634,7 +625,7 @@ QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivat
QQmlType base;
if (d->regType == CompositeType)
- base = resolveCompositeBaseType(engine);
+ base = d->resolveCompositeBaseType(engine);
return base.attachedPropertiesFunction(engine);
}
@@ -647,7 +638,7 @@ const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) c
QQmlType base;
if (d->regType == CompositeType)
- base = resolveCompositeBaseType(engine);
+ base = d->resolveCompositeBaseType(engine);
return base.attachedPropertiesType(engine);
}
@@ -666,7 +657,7 @@ int QQmlType::attachedPropertiesId(QQmlEnginePrivate *engine) const
QQmlType base;
if (d->regType == CompositeType)
- base = resolveCompositeBaseType(engine);
+ base = d->resolveCompositeBaseType(engine);
return base.attachedPropertiesId(engine);
}
#endif
@@ -706,24 +697,16 @@ int QQmlType::index() const
QUrl QQmlType::sourceUrl() const
{
- if (d) {
- if (d->regType == CompositeType)
- return d->extraData.fd->url;
- else if (d->regType == CompositeSingletonType)
- return d->extraData.sd->singletonInstanceInfo->url;
- }
- return QUrl();
+ return d ? d->sourceUrl() : QUrl();
}
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
-
*ok = true;
- d->initEnums(cache);
+ d->initEnums(engine);
int *rv = d->enums.value(name);
if (rv)
@@ -738,11 +721,9 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name
{
Q_ASSERT(ok);
if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
-
*ok = true;
- d->initEnums(cache);
+ d->initEnums(engine);
int *rv = d->enums.value(name);
if (rv)
@@ -757,10 +738,9 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool
{
Q_ASSERT(ok);
if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
*ok = true;
- d->initEnums(cache);
+ d->initEnums(engine);
int *rv = d->enums.value(name);
if (rv)
@@ -775,10 +755,9 @@ int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name
{
Q_ASSERT(ok);
if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
*ok = true;
- d->initEnums(cache);
+ d->initEnums(engine);
int *rv = d->scopedEnumIndex.value(name);
if (rv)
@@ -793,10 +772,9 @@ int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bo
{
Q_ASSERT(ok);
if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
*ok = true;
- d->initEnums(cache);
+ d->initEnums(engine);
int *rv = d->scopedEnumIndex.value(name);
if (rv)
@@ -845,10 +823,9 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scope
{
Q_ASSERT(ok);
if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
*ok = true;
- d->initEnums(cache);
+ d->initEnums(engine);
int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length()));
if (rv) {
@@ -868,10 +845,9 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scope
{
Q_ASSERT(ok);
if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
*ok = true;
- d->initEnums(cache);
+ d->initEnums(engine);
int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName));
if (rv) {
diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h
index 158fefad2c..ec27b38a73 100644
--- a/src/qml/qml/qqmltype_p.h
+++ b/src/qml/qml/qqmltype_p.h
@@ -182,12 +182,7 @@ public:
};
private:
- QQmlType superType() const;
- QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
- int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
- QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const;
friend uint qHash(const QQmlType &t, uint seed);
-
QQmlRefPointer<const QQmlTypePrivate> d;
};
diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h
index d381e11df4..6a2d961de8 100644
--- a/src/qml/qml/qqmltype_p_p.h
+++ b/src/qml/qml/qqmltype_p_p.h
@@ -66,10 +66,30 @@ public:
QQmlTypePrivate(QQmlType::RegistrationType type);
void init() const;
- void initEnums(const QQmlPropertyCache *cache = nullptr) const;
+ void initEnums(QQmlEnginePrivate *engine) const;
void insertEnums(const QMetaObject *metaObject) const;
void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
+ QUrl sourceUrl() const
+ {
+ switch (regType) {
+ case QQmlType::CompositeType:
+ return extraData.fd->url;
+ case QQmlType::CompositeSingletonType:
+ return extraData.sd->singletonInstanceInfo->url;
+ default:
+ return QUrl();
+ }
+ }
+
+ bool isComposite() const
+ {
+ return regType == QQmlType::CompositeType || regType == QQmlType::CompositeSingletonType;
+ }
+
+ QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
+ QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const;
+
QQmlType::RegistrationType regType;
struct QQmlCppTypeData
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index e7633a1bba..9ff0e3fb9e 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -158,6 +158,9 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
QmlIR::QmlUnitGenerator qmlGenerator;
qmlGenerator.generate(*document, dependencyHasher);
+ if (!errors.isEmpty())
+ return nullptr;
+
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
= QV4::ExecutableCompilationUnit::create(std::move(
document->javaScriptCompilationUnit));
@@ -165,11 +168,7 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
compilationUnit->resolvedTypes = *resolvedTypes;
compilationUnit->propertyCaches = std::move(m_propertyCaches);
Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast<int>(compilationUnit->objectCount()));
-
- if (errors.isEmpty())
- return compilationUnit;
- else
- return nullptr;
+ return compilationUnit;
}
void QQmlTypeCompiler::recordError(const QV4::CompiledData::Location &location, const QString &description)
@@ -328,18 +327,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
auto *typeRef = resolvedType(binding->propertyNameIndex);
QQmlType type = typeRef ? typeRef->type : QQmlType();
- if (!type.isValid()) {
- if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) {
- if (type.isComposite()) {
- QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(type.sourceUrl());
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
-
- auto compilationUnit = tdata->compilationUnit();
- type = QQmlMetaType::qmlType(compilationUnit->metaTypeId);
- }
- }
- }
+ if (!type.isValid())
+ imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr);
const QMetaObject *attachedType = type.attachedPropertiesType(enginePrivate);
if (!attachedType)
@@ -1027,7 +1016,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex)
}
if (result == AllAliasesResolved) {
- QQmlJS::DiagnosticMessage error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex);
+ QQmlJS::DiagnosticMessage error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex, enginePrivate);
if (error.isValid()) {
recordError(error);
return false;
@@ -1154,23 +1143,42 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
if (!subProperty.isEmpty()) {
const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(targetProperty->propType());
if (!valueTypeMetaObject) {
- *error = qQmlCompileError(
- alias->referenceLocation,
- tr("Invalid alias target location: %1").arg(subProperty.toString()));
- break;
- }
+ // could be a deep alias
+ bool isDeepAlias = subProperty.at(0).isLower();
+ if (isDeepAlias) {
+ isDeepAlias = false;
+ for (auto it = targetObject->bindingsBegin(); it != targetObject->bindingsEnd(); ++it) {
+ auto binding = *it;
+ if (compiler->stringAt(binding.propertyNameIndex) == property) {
+ resolver = QQmlPropertyResolver(propertyCaches.at(binding.value.objectIndex));
+ QQmlPropertyData *actualProperty = resolver.property(subProperty.toString());
+ if (actualProperty) {
+ propIdx = QQmlPropertyIndex(propIdx.coreIndex(), actualProperty->coreIndex());
+ isDeepAlias = true;
+ }
+ }
+ }
+ }
+ if (!isDeepAlias) {
+ *error = qQmlCompileError(
+ alias->referenceLocation,
+ tr("Invalid alias target location: %1").arg(subProperty.toString()));
+ break;
+ }
+ } else {
- int valueTypeIndex =
- valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
- if (valueTypeIndex == -1) {
- *error = qQmlCompileError(
- alias->referenceLocation,
- tr("Invalid alias target location: %1").arg(subProperty.toString()));
- break;
- }
- Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
+ int valueTypeIndex =
+ valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
+ if (valueTypeIndex == -1) {
+ *error = qQmlCompileError(
+ alias->referenceLocation,
+ tr("Invalid alias target location: %1").arg(subProperty.toString()));
+ break;
+ }
+ Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
- propIdx = QQmlPropertyIndex(propIdx.coreIndex(), valueTypeIndex);
+ propIdx = QQmlPropertyIndex(propIdx.coreIndex(), valueTypeIndex);
+ }
} else {
if (targetProperty->isQObject())
alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index 8d75b57fc1..cfdcf6aad5 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -209,7 +209,7 @@ void QQmlTypeData::createTypeAndPropertyCaches(
QQmlPropertyCacheAliasCreator<QV4::ExecutableCompilationUnit> aliasCreator(
&m_compiledData->propertyCaches, m_compiledData.data());
- aliasCreator.appendAliasPropertiesToMetaObjects();
+ aliasCreator.appendAliasPropertiesToMetaObjects(engine);
pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches);
}
@@ -305,6 +305,7 @@ void QQmlTypeData::done()
QQmlJS::DiagnosticMessage error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
if (error.isValid()) {
setError(error);
+ qDeleteAll(resolvedTypeCache);
return;
}
}
@@ -614,6 +615,8 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCach
QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache, dependencyHasher);
m_compiledData = compiler.compile();
if (!m_compiledData) {
+ qDeleteAll(*resolvedTypeCache);
+ resolvedTypeCache->clear();
setError(compiler.compilationErrors());
return;
}
@@ -678,7 +681,7 @@ void QQmlTypeData::resolveTypes()
if (ref.type.isCompositeSingleton()) {
ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
- if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies) {
+ if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies || m_waitingOnMe.contains(ref.typeData.data())) {
// TODO: give an error message? If so, we should record and show the path of the cycle.
continue;
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 3a18bbf7c9..c62f760ee3 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -491,7 +491,7 @@ bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, PendingImportPtr import,
{
QQmlRefPointer<QQmlQmldirData> data = typeLoader()->getQmldir(url);
- data->setImport(this, import);
+ data->setImport(this, std::move(import));
data->setPriority(this, priority);
if (data->status() == Error) {
@@ -563,13 +563,7 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo
QString qmldirFilePath;
QString qmldirUrl;
- if (QQmlMetaType::isLockedModule(import->uri, import->majorVersion)) {
- //Locked modules are checked first, to save on filesystem checks
- if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion,
- import->minorVersion, QString(), QString(), false, errors))
- return false;
-
- } else if (m_importCache.locateQmldir(importDatabase, import->uri, import->majorVersion, import->minorVersion,
+ if (m_importCache.locateQmldir(importDatabase, import->uri, import->majorVersion, import->minorVersion,
&qmldirFilePath, &qmldirUrl)) {
// This is a local library import
if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion,
@@ -964,8 +958,10 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path)
bool QQmlTypeLoader::fileExists(const QString &path, const QString &file)
{
- if (path.isEmpty())
+ const QChar nullChar(QChar::Null);
+ if (path.isEmpty() || path.contains(nullChar) || file.isEmpty() || file.contains(nullChar))
return false;
+
Q_ASSERT(path.endsWith(QLatin1Char('/')));
if (path.at(0) == QLatin1Char(':')) {
// qrc resource
diff --git a/src/qml/qml/qqmltypeloaderqmldircontent.cpp b/src/qml/qml/qqmltypeloaderqmldircontent.cpp
index 238af9b710..8e983db756 100644
--- a/src/qml/qml/qqmltypeloaderqmldircontent.cpp
+++ b/src/qml/qml/qqmltypeloaderqmldircontent.cpp
@@ -55,7 +55,8 @@ QList<QQmlError> QQmlTypeLoaderQmldirContent::errors(const QString &uri) const
{
QList<QQmlError> errors;
const QUrl url(uri);
- for (const auto parseError : m_parser.errors(uri)) {
+ const auto parseErrors = m_parser.errors(uri);
+ for (const auto &parseError : parseErrors) {
QQmlError error;
error.setUrl(url);
error.setLine(parseError.line);
diff --git a/src/qml/qml/qqmltypenotavailable_p.h b/src/qml/qml/qqmltypenotavailable_p.h
index 33630bf507..8db5876b10 100644
--- a/src/qml/qml/qqmltypenotavailable_p.h
+++ b/src/qml/qml/qqmltypenotavailable_p.h
@@ -58,6 +58,9 @@ QT_BEGIN_NAMESPACE
class QQmlTypeNotAvailable : public QObject {
Q_OBJECT
+ QML_NAMED_ELEMENT(TypeNotAvailable)
+ QML_UNCREATABLE("Type not available.")
+
public:
QQmlTypeNotAvailable();
};
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 931f37b35a..ef4a628a04 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -476,6 +476,34 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object,
}
// Fall through to base implementation
}
+
+ if (name->startsWithUpper()) {
+ bool ok = false;
+ int value = type.enumValue(QQmlEnginePrivate::get(engine->qmlEngine()), name, &ok);
+ if (ok) {
+ lookup->qmlEnumValueLookup.ic = This->internalClass();
+ lookup->qmlEnumValueLookup.encodedEnumValue
+ = QV4::Value::fromInt32(value).asReturnedValue();
+ lookup->getter = QQmlTypeWrapper::lookupEnumValue;
+ return lookup->getter(lookup, engine, *object);
+ }
+
+ value = type.scopedEnumIndex(QQmlEnginePrivate::get(engine->qmlEngine()), name, &ok);
+ if (ok) {
+ Scoped<QQmlScopedEnumWrapper> enumWrapper(
+ scope, engine->memoryManager->allocate<QQmlScopedEnumWrapper>());
+ enumWrapper->d()->typePrivate = type.priv();
+ QQmlType::refHandle(enumWrapper->d()->typePrivate);
+ enumWrapper->d()->scopeEnumIndex = value;
+
+ lookup->qmlScopedEnumWrapperLookup.ic = This->internalClass();
+ lookup->qmlScopedEnumWrapperLookup.qmlScopedEnumWrapper
+ = static_cast<Heap::Object*>(enumWrapper->heapObject());
+ lookup->getter = QQmlTypeWrapper::lookupScopedEnum;
+ return enumWrapper.asReturnedValue();
+ }
+ // Fall through to base implementation
+ }
// Fall through to base implementation
}
return QV4::Object::virtualResolveLookupGetter(object, engine, lookup);
@@ -519,6 +547,34 @@ ReturnedValue QQmlTypeWrapper::lookupSingletonProperty(Lookup *l, ExecutionEngin
return QObjectWrapper::lookupGetterImpl(l, engine, obj, /*useOriginalProperty*/ true, revertLookup);
}
+ReturnedValue QQmlTypeWrapper::lookupEnumValue(Lookup *l, ExecutionEngine *engine, const Value &base)
+{
+ auto *o = static_cast<Heap::Object *>(base.heapObject());
+ if (!o || o->internalClass != l->qmlEnumValueLookup.ic) {
+ l->getter = Lookup::getterGeneric;
+ return Lookup::getterGeneric(l, engine, base);
+ }
+
+ return l->qmlEnumValueLookup.encodedEnumValue;
+}
+
+ReturnedValue QQmlTypeWrapper::lookupScopedEnum(Lookup *l, ExecutionEngine *engine, const Value &base)
+{
+ Scope scope(engine);
+ Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, static_cast<Heap::QQmlScopedEnumWrapper *>(
+ l->qmlScopedEnumWrapperLookup.qmlScopedEnumWrapper));
+
+ auto *o = static_cast<Heap::Object *>(base.heapObject());
+ if (!o || o->internalClass != l->qmlScopedEnumWrapperLookup.ic) {
+ QQmlType::derefHandle(enumWrapper->d()->typePrivate);
+ l->qmlScopedEnumWrapperLookup.qmlScopedEnumWrapper = nullptr;
+ l->getter = Lookup::getterGeneric;
+ return Lookup::getterGeneric(l, engine, base);
+ }
+
+ return enumWrapper.asReturnedValue();
+}
+
void Heap::QQmlScopedEnumWrapper::destroy()
{
QQmlType::derefHandle(typePrivate);
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 6b51f421b3..7dc3f55310 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -115,6 +115,8 @@ struct Q_QML_EXPORT QQmlTypeWrapper : Object
static bool virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value);
static ReturnedValue lookupSingletonProperty(Lookup *l, ExecutionEngine *engine, const Value &base);
+ static ReturnedValue lookupEnumValue(Lookup *l, ExecutionEngine *engine, const Value &base);
+ static ReturnedValue lookupScopedEnum(Lookup *l, ExecutionEngine *engine, const Value &base);
protected:
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 2225191a9d..d83fc4bb48 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -65,11 +65,13 @@ struct QQmlValueTypeFactoryImpl
QQmlValueType *valueTypes[QVariant::UserType];
QHash<int, QQmlValueType *> userTypes;
QMutex mutex;
+
+ QQmlValueType invalidValueType;
};
QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl()
{
- std::fill_n(valueTypes, int(QVariant::UserType), nullptr);
+ std::fill_n(valueTypes, int(QVariant::UserType), &invalidValueType);
#if QT_CONFIG(qml_itemmodel)
// See types wrapped in qqmlmodelindexvaluetype_p.h
@@ -79,20 +81,18 @@ QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl()
QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl()
{
- qDeleteAll(valueTypes, valueTypes + QVariant::UserType);
+ for (QQmlValueType *type : valueTypes) {
+ if (type != &invalidValueType)
+ delete type;
+ }
qDeleteAll(userTypes);
}
-bool QQmlValueTypeFactoryImpl::isValueType(int idx)
+bool isInternalType(int idx)
{
- if (idx >= QMetaType::User)
- return valueType(idx) != nullptr;
-
- if (idx < 0)
- return false;
-
// Qt internal types
switch (idx) {
+ case QMetaType::UnknownType:
case QMetaType::QStringList:
case QMetaType::QObjectStar:
case QMetaType::VoidStar:
@@ -101,12 +101,20 @@ bool QQmlValueTypeFactoryImpl::isValueType(int idx)
case QMetaType::QLocale:
case QMetaType::QImage: // scarce type, keep as QVariant
case QMetaType::QPixmap: // scarce type, keep as QVariant
- return false;
- default:
return true;
+ default:
+ return false;
}
}
+bool QQmlValueTypeFactoryImpl::isValueType(int idx)
+{
+ if (idx < 0 || isInternalType(idx))
+ return false;
+
+ return valueType(idx) != nullptr;
+}
+
const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t)
{
switch (t) {
@@ -168,15 +176,17 @@ QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx)
}
QQmlValueType *rv = valueTypes[idx];
- if (!rv) {
+ if (rv == &invalidValueType) {
// No need for mutex protection - the most we can lose is a valueType instance
// TODO: Investigate the performance/memory characteristics of
// removing the preallocated array
- if (const QMetaObject *mo = metaObjectForMetaType(idx)) {
- rv = new QQmlValueType(idx, mo);
- valueTypes[idx] = rv;
- }
+ if (isInternalType(idx))
+ rv = valueTypes[idx] = nullptr;
+ else if (const QMetaObject *mo = metaObjectForMetaType(idx))
+ rv = valueTypes[idx] = new QQmlValueType(idx, mo);
+ else
+ rv = valueTypes[idx] = nullptr;
}
return rv;
@@ -208,6 +218,13 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor,
#endif
}
+QQmlValueType::QQmlValueType() :
+ _metaObject(nullptr),
+ gadgetPtr(nullptr),
+ metaType(QMetaType::UnknownType)
+{
+}
+
QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
: gadgetPtr(QMetaType::create(typeId))
, metaType(typeId)
@@ -225,7 +242,7 @@ QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
QQmlValueType::~QQmlValueType()
{
QObjectPrivate *op = QObjectPrivate::get(this);
- Q_ASSERT(op->metaObject == this);
+ Q_ASSERT(op->metaObject == nullptr || op->metaObject == this);
op->metaObject = nullptr;
::free(const_cast<QMetaObject *>(_metaObject));
metaType.destroy(gadgetPtr);
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 75150b3f32..0601237c4b 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -68,6 +68,7 @@ QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject, public QAbstractDynamicMetaObject
{
public:
+ QQmlValueType();
QQmlValueType(int userType, const QMetaObject *metaObject);
~QQmlValueType() override;
void read(QObject *, int);
@@ -92,7 +93,7 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory
{
public:
- static bool isValueType(int);
+ static bool isValueType(int idx);
static QQmlValueType *valueType(int idx);
static const QMetaObject *metaObjectForMetaType(int type);
@@ -217,6 +218,8 @@ struct QQmlEasingValueType
{
QEasingCurve v;
Q_GADGET
+ QML_NAMED_ELEMENT(Easing)
+ QML_UNCREATABLE("Use the Type enum.")
Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL)
Q_PROPERTY(qreal amplitude READ amplitude WRITE setAmplitude FINAL)
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index cf6553d129..f23921497c 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -96,29 +96,29 @@ using namespace QV4;
void Heap::QQmlValueTypeWrapper::destroy()
{
- if (gadgetPtr) {
- valueType->metaType.destruct(gadgetPtr);
- ::operator delete(gadgetPtr);
+ if (m_gadgetPtr) {
+ m_valueType->metaType.destruct(m_gadgetPtr);
+ ::operator delete(m_gadgetPtr);
}
- if (_propertyCache)
- _propertyCache->release();
+ if (m_propertyCache)
+ m_propertyCache->release();
Object::destroy();
}
void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
{
- Q_ASSERT(valueType->metaType.id() == value.userType());
- if (gadgetPtr)
- valueType->metaType.destruct(gadgetPtr);
- if (!gadgetPtr)
- gadgetPtr = ::operator new(valueType->metaType.sizeOf());
- valueType->metaType.construct(gadgetPtr, value.constData());
+ Q_ASSERT(valueType()->metaType.id() == value.userType());
+ if (auto *gadget = gadgetPtr())
+ valueType()->metaType.destruct(gadget);
+ if (!gadgetPtr())
+ setGadgetPtr(::operator new(valueType()->metaType.sizeOf()));
+ valueType()->metaType.construct(gadgetPtr(), value.constData());
}
QVariant Heap::QQmlValueTypeWrapper::toVariant() const
{
- Q_ASSERT(gadgetPtr);
- return QVariant(valueType->metaType.id(), gadgetPtr);
+ Q_ASSERT(gadgetPtr());
+ return QVariant(valueType()->metaType.id(), gadgetPtr());
}
@@ -146,13 +146,13 @@ bool QQmlValueTypeReference::readReferenceValue() const
QQmlPropertyCache *cache = nullptr;
if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType))
cache = QJSEnginePrivate::get(engine())->cache(mo);
- if (d()->gadgetPtr) {
- d()->valueType->metaType.destruct(d()->gadgetPtr);
- ::operator delete(d()->gadgetPtr);
+ if (d()->gadgetPtr()) {
+ d()->valueType()->metaType.destruct(d()->gadgetPtr());
+ ::operator delete(d()->gadgetPtr());
}
- d()->gadgetPtr =nullptr;
+ d()->setGadgetPtr(nullptr);
d()->setPropertyCache(cache);
- d()->valueType = QQmlValueTypeFactory::valueType(variantReferenceType);
+ d()->setValueType(QQmlValueTypeFactory::valueType(variantReferenceType));
if (!cache)
return false;
} else {
@@ -161,12 +161,12 @@ bool QQmlValueTypeReference::readReferenceValue() const
}
d()->setValue(variantReferenceValue);
} else {
- if (!d()->gadgetPtr) {
- d()->gadgetPtr = ::operator new(d()->valueType->metaType.sizeOf());
- d()->valueType->metaType.construct(d()->gadgetPtr, nullptr);
+ if (!d()->gadgetPtr()) {
+ d()->setGadgetPtr(::operator new(d()->valueType()->metaType.sizeOf()));
+ d()->valueType()->metaType.construct(d()->gadgetPtr(), nullptr);
}
// value-type reference
- void *args[] = { d()->gadgetPtr, nullptr };
+ void *args[] = { d()->gadgetPtr(), nullptr };
QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, args);
}
return true;
@@ -192,8 +192,8 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
r->d()->object = object;
r->d()->property = property;
r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
- r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
- r->d()->gadgetPtr = nullptr;
+ r->d()->setValueType(QQmlValueTypeFactory::valueType(typeId));
+ r->d()->setGadgetPtr(nullptr);
return r->asReturnedValue();
}
@@ -204,8 +204,8 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocate<QQmlValueTypeWrapper>());
r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
- r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
- r->d()->gadgetPtr = nullptr;
+ r->d()->setValueType(QQmlValueTypeFactory::valueType(typeId));
+ r->d()->setGadgetPtr(nullptr);
r->d()->setValue(value);
return r->asReturnedValue();
}
@@ -223,9 +223,9 @@ bool QQmlValueTypeWrapper::toGadget(void *data) const
if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return false;
- const int typeId = d()->valueType->metaType.id();
+ const int typeId = d()->valueType()->metaType.id();
QMetaType::destruct(typeId, data);
- QMetaType::construct(typeId, data, d()->gadgetPtr);
+ QMetaType::construct(typeId, data, d()->gadgetPtr());
return true;
}
@@ -307,7 +307,7 @@ bool QQmlValueTypeWrapper::isEqual(const QVariant& value) const
int QQmlValueTypeWrapper::typeId() const
{
- return d()->valueType->metaType.id();
+ return d()->valueType()->metaType.id();
}
bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
@@ -315,10 +315,10 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
bool destructGadgetOnExit = false;
Q_ALLOCA_DECLARE(void, gadget);
if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>()) {
- if (!d()->gadgetPtr) {
- Q_ALLOCA_ASSIGN(void, gadget, d()->valueType->metaType.sizeOf());
- d()->gadgetPtr = gadget;
- d()->valueType->metaType.construct(d()->gadgetPtr, nullptr);
+ if (!d()->gadgetPtr()) {
+ Q_ALLOCA_ASSIGN(void, gadget, d()->valueType()->metaType.sizeOf());
+ d()->setGadgetPtr(gadget);
+ d()->valueType()->metaType.construct(d()->gadgetPtr(), nullptr);
destructGadgetOnExit = true;
}
if (!ref->readReferenceValue())
@@ -327,12 +327,12 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
int flags = 0;
int status = -1;
- void *a[] = { d()->gadgetPtr, nullptr, &status, &flags };
+ void *a[] = { d()->gadgetPtr(), nullptr, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty, propertyIndex, a);
if (destructGadgetOnExit) {
- d()->valueType->metaType.destruct(d()->gadgetPtr);
- d()->gadgetPtr = nullptr;
+ d()->valueType()->metaType.destruct(d()->gadgetPtr());
+ d()->setGadgetPtr(nullptr);
}
return true;
}
@@ -354,16 +354,16 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(const FunctionObject *b, con
// Prepare a buffer to pass to QMetaType::convert()
QString convertResult;
convertResult.~QString();
- if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->metaType.id(), &convertResult, QMetaType::QString)) {
+ if (QMetaType::convert(w->d()->gadgetPtr(), w->d()->valueType()->metaType.id(), &convertResult, QMetaType::QString)) {
result = convertResult;
} else {
- result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->metaType.id()))
+ result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType()->metaType.id()))
+ QLatin1Char('(');
const QMetaObject *mo = w->d()->propertyCache()->metaObject();
const int propCount = mo->propertyCount();
for (int i = 0; i < propCount; ++i) {
if (mo->property(i).isDesignable()) {
- QVariant value = mo->property(i).readOnGadget(w->d()->gadgetPtr);
+ QVariant value = mo->property(i).readOnGadget(w->d()->gadgetPtr());
if (i > 0)
result += QLatin1String(", ");
result += value.toString();
@@ -387,7 +387,7 @@ Q_ALWAYS_INLINE static ReturnedValue getGadgetProperty(ExecutionEngine *engine,
if (property->propType() == metatype) { \
cpptype v; \
void *args[] = { &v, nullptr }; \
- metaObject->d.static_metacall(reinterpret_cast<QObject*>(valueTypeWrapper->gadgetPtr), \
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(valueTypeWrapper->gadgetPtr()), \
QMetaObject::ReadProperty, index, args); \
return QV4::Encode(constructor(v)); \
}
@@ -412,7 +412,7 @@ Q_ALWAYS_INLINE static ReturnedValue getGadgetProperty(ExecutionEngine *engine,
v = QVariant(property->propType(), static_cast<void *>(nullptr));
args[0] = v.data();
}
- metaObject->d.static_metacall(reinterpret_cast<QObject*>(valueTypeWrapper->gadgetPtr), QMetaObject::ReadProperty,
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(valueTypeWrapper->gadgetPtr()), QMetaObject::ReadProperty,
index, args);
return engine->fromVariant(v);
#undef VALUE_TYPE_LOAD
@@ -604,7 +604,7 @@ bool QQmlValueTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &v
if (property.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
v = v.toInt();
- void *gadget = r->d()->gadgetPtr;
+ void *gadget = r->d()->gadgetPtr();
property.writeOnGadget(gadget, v);
@@ -620,7 +620,7 @@ bool QQmlValueTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &v
} else {
int flags = 0;
int status = -1;
- void *a[] = { r->d()->gadgetPtr, nullptr, &status, &flags };
+ void *a[] = { r->d()->gadgetPtr(), nullptr, &status, &flags };
QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
}
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index baac129afa..60079aa623 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -69,22 +69,45 @@ namespace Heap {
struct QQmlValueTypeWrapper : Object {
void init() { Object::init(); }
void destroy();
- QQmlPropertyCache *propertyCache() const { return _propertyCache; }
+
+ QQmlPropertyCache *propertyCache() const { return m_propertyCache; }
void setPropertyCache(QQmlPropertyCache *c) {
if (c)
c->addref();
- if (_propertyCache)
- _propertyCache->release();
- _propertyCache = c;
+ if (m_propertyCache)
+ m_propertyCache->release();
+ m_propertyCache = c;
+ }
+
+ void setValueType(QQmlValueType *valueType)
+ {
+ Q_ASSERT(valueType != nullptr);
+ m_valueType = valueType;
+ }
+
+ QQmlValueType *valueType() const
+ {
+ Q_ASSERT(m_valueType != nullptr);
+ return m_valueType;
+ }
+
+ void setGadgetPtr(void *gadgetPtr) const
+ {
+ m_gadgetPtr = gadgetPtr;
+ }
+
+ void *gadgetPtr() const
+ {
+ return m_gadgetPtr;
}
- mutable void *gadgetPtr;
- QQmlValueType *valueType;
void setValue(const QVariant &value) const;
QVariant toVariant() const;
private:
- QQmlPropertyCache *_propertyCache;
+ mutable void *m_gadgetPtr;
+ QQmlValueType *m_valueType;
+ QQmlPropertyCache *m_propertyCache;
};
}
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index b9d8fed243..9b5490b6e5 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -164,8 +164,19 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
QQmlData *targetDData = QQmlData::get(target, /*create*/false);
if (!targetDData)
return;
- int coreIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex).coreIndex();
+ QQmlPropertyIndex encodedIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex);
+ int coreIndex = encodedIndex.coreIndex();
+ int valueTypeIndex = encodedIndex.valueTypeIndex();
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
+ if (pd && valueTypeIndex != -1 && !QQmlValueTypeFactory::valueType(pd->propType())) {
+ // deep alias
+ QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(metaObject->compilationUnit->engine->qmlEngine());
+ auto const *newPropertyCache = enginePriv->propertyCacheForType(pd->propType());
+ void *argv[1] = { &target };
+ QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, argv);
+ Q_ASSERT(newPropertyCache);
+ pd = newPropertyCache->property(valueTypeIndex);
+ }
if (!pd)
return;
@@ -858,17 +869,23 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (!targetDData->propertyCache)
return -1;
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
- // Value type property
+ // Value type property or deep alias
QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType());
- Q_ASSERT(valueType);
+ if (valueType) {
- valueType->read(target, coreIndex);
- int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a);
+ valueType->read(target, coreIndex);
+ int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a);
- if (c == QMetaObject::WriteProperty)
- valueType->write(target, coreIndex, nullptr);
+ if (c == QMetaObject::WriteProperty)
+ valueType->write(target, coreIndex, nullptr);
- return rv;
+ return rv;
+ } else {
+ // deep alias
+ void *argv[1] = { &target };
+ QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, argv);
+ return QMetaObject::metacall(target, c, valueTypePropertyIndex, a);
+ }
} else {
return QMetaObject::metacall(target, c, coreIndex, a);
@@ -1180,6 +1197,8 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
const int aliasId = index - propOffset() - compiledObject->nProperties;
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
+ while (aliasData->aliasToLocalAlias)
+ aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
*target = ctxt->idValues[aliasData->targetObjectId].data();
if (!*target)
return false;
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 2e213e7dc3..d634a48443 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -229,8 +229,10 @@ OwnPropertyKeyIterator *QtObject::virtualOwnPropertyKeys(const Object *m, Value
}
/*!
-\qmlmethod bool Qt::isQtObject(object)
-Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
+ \qmlmethod bool Qt::isQtObject(object)
+
+ Returns \c true if \a object is a valid reference to a Qt or QML object,
+ \c false otherwise.
*/
ReturnedValue QtObject::method_isQtObject(const FunctionObject *, const Value *, const Value *argv, int argc)
{
@@ -241,10 +243,10 @@ ReturnedValue QtObject::method_isQtObject(const FunctionObject *, const Value *,
}
/*!
-\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
+ \qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
-Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
-All components should be in the range 0-1 inclusive.
+ Returns a color with the specified \a red, \a green, \a blue, and \a alpha
+ components. All components should be in the range 0-1 (inclusive).
*/
ReturnedValue QtObject::method_rgba(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
@@ -270,10 +272,10 @@ ReturnedValue QtObject::method_rgba(const FunctionObject *f, const Value *, cons
}
/*!
-\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
+ \qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
-Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
-All components should be in the range 0-1 inclusive.
+ Returns a color with the specified \a hue, \a saturation, \a lightness, and \a alpha
+ components. All components should be in the range 0-1 (inclusive).
*/
ReturnedValue QtObject::method_hsla(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -300,12 +302,12 @@ ReturnedValue QtObject::method_hsla(const FunctionObject *b, const Value *, cons
}
/*!
-\qmlmethod color Qt::hsva(real hue, real saturation, real value, real alpha)
+ \since 5.5
+ \qmlmethod color Qt::hsva(real hue, real saturation, real value, real alpha)
-Returns a color with the specified \c hue, \c saturation, \c value and \c alpha components.
-All components should be in the range 0-1 inclusive.
+ Returns a color with the specified \a hue, \a saturation, \a value and \a alpha
+ components. All components should be in the range 0-1 (inclusive).
-\since 5.5
*/
ReturnedValue QtObject::method_hsva(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -328,12 +330,12 @@ ReturnedValue QtObject::method_hsva(const FunctionObject *b, const Value *, cons
}
/*!
-\qmlmethod color Qt::colorEqual(color lhs, string rhs)
+ \qmlmethod color Qt::colorEqual(color lhs, string rhs)
-Returns true if both \c lhs and \c rhs yield equal color values. Both arguments
-may be either color values or string values. If a string value is supplied it
-must be convertible to a color, as described for the \l{colorbasictypedocs}{color}
-basic type.
+ Returns \c true if both \a lhs and \a rhs yield equal color values. Both
+ arguments may be either color values or string values. If a string value
+ is supplied it must be convertible to a color, as described for the
+ \l{colorbasictypedocs}{color} basic type.
*/
ReturnedValue QtObject::method_colorEqual(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -368,11 +370,9 @@ ReturnedValue QtObject::method_colorEqual(const FunctionObject *b, const Value *
}
/*!
-\qmlmethod rect Qt::rect(int x, int y, int width, int height)
-
-Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
+ \qmlmethod rect Qt::rect(int x, int y, int width, int height)
-The returned object has \c x, \c y, \c width and \c height attributes with the given values.
+ Returns a rect with the top-left corner at \a x, \a y and the specified \a width and \a height.
*/
ReturnedValue QtObject::method_rect(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -389,8 +389,9 @@ ReturnedValue QtObject::method_rect(const FunctionObject *b, const Value *, cons
}
/*!
-\qmlmethod point Qt::point(int x, int y)
-Returns a Point with the specified \c x and \c y coordinates.
+ \qmlmethod point Qt::point(int x, int y)
+
+ Returns a point with the specified \a x and \a y coordinates.
*/
ReturnedValue QtObject::method_point(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -405,8 +406,9 @@ ReturnedValue QtObject::method_point(const FunctionObject *b, const Value *, con
}
/*!
-\qmlmethod Qt::size(int width, int height)
-Returns a Size with the specified \c width and \c height.
+ \qmlmethod size Qt::size(int width, int height)
+
+ Returns a size with the specified \a width and \a height.
*/
ReturnedValue QtObject::method_size(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -421,12 +423,13 @@ ReturnedValue QtObject::method_size(const FunctionObject *b, const Value *, cons
}
/*!
-\qmlmethod Qt::font(object fontSpecifier)
-Returns a Font with the properties specified in the \c fontSpecifier object
-or the nearest matching font. The \c fontSpecifier object should contain
-key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's
-subproperty names, and the values are valid values for each subproperty.
-Invalid keys will be ignored.
+ \qmlmethod font Qt::font(object fontSpecifier)
+
+ Returns a font with the properties specified in the \a fontSpecifier object
+ or the nearest matching font. The \a fontSpecifier object should contain
+ key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's
+ subproperty names, and the values are valid values for each subproperty.
+ Invalid keys will be ignored.
*/
ReturnedValue QtObject::method_font(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -445,8 +448,9 @@ ReturnedValue QtObject::method_font(const FunctionObject *b, const Value *, cons
/*!
-\qmlmethod Qt::vector2d(real x, real y)
-Returns a Vector2D with the specified \c x and \c y.
+ \qmlmethod vector2d Qt::vector2d(real x, real y)
+
+ Returns a vector2d with the specified \a x and \a y values.
*/
ReturnedValue QtObject::method_vector2d(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -463,8 +467,9 @@ ReturnedValue QtObject::method_vector2d(const FunctionObject *b, const Value *,
}
/*!
-\qmlmethod Qt::vector3d(real x, real y, real z)
-Returns a Vector3D with the specified \c x, \c y and \c z.
+ \qmlmethod vector3d Qt::vector3d(real x, real y, real z)
+
+ Returns a vector3d with the specified \a x, \a y, and \a z values.
*/
ReturnedValue QtObject::method_vector3d(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -482,8 +487,9 @@ ReturnedValue QtObject::method_vector3d(const FunctionObject *b, const Value *,
}
/*!
-\qmlmethod Qt::vector4d(real x, real y, real z, real w)
-Returns a Vector4D with the specified \c x, \c y, \c z and \c w.
+ \qmlmethod vector4d Qt::vector4d(real x, real y, real z, real w)
+
+ Returns a vector4d with the specified \a x, \a y, \a z, and \a w values.
*/
ReturnedValue QtObject::method_vector4d(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -502,8 +508,9 @@ ReturnedValue QtObject::method_vector4d(const FunctionObject *b, const Value *,
}
/*!
-\qmlmethod Qt::quaternion(real scalar, real x, real y, real z)
-Returns a Quaternion with the specified \c scalar, \c x, \c y, and \c z.
+ \qmlmethod quaternion Qt::quaternion(real scalar, real x, real y, real z)
+
+ Returns a quaternion with the specified \a scalar, \a x, \a y, and \a z values.
*/
ReturnedValue QtObject::method_quaternion(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -522,13 +529,25 @@ ReturnedValue QtObject::method_quaternion(const FunctionObject *b, const Value *
}
/*!
-\qmlmethod Qt::matrix4x4(real m11, real m12, real m13, real m14, real m21, real m22, real m23, real m24, real m31, real m32, real m33, real m34, real m41, real m42, real m43, real m44)
-Returns a Matrix4x4 with the specified values.
-Alternatively, the function may be called with a single argument
-where that argument is a JavaScript array which contains the sixteen
-matrix values.
-Finally, the function may be called with no arguments and the resulting
-matrix will be the identity matrix.
+ \qmlmethod matrix4x4 Qt::matrix4x4(real m11, real m12, real m13, real m14, real m21, real m22, real m23, real m24, real m31, real m32, real m33, real m34, real m41, real m42, real m43, real m44)
+
+ Returns a matrix4x4 with the specified values.
+
+ The arguments correspond to their positions in the matrix:
+
+ \table
+ \row \li \a m11 \li \a m12 \li \a m13 \li \a m14
+ \row \li \a m21 \li \a m22 \li \a m23 \li \a m24
+ \row \li \a m31 \li \a m32 \li \a m33 \li \a m34
+ \row \li \a m41 \li \a m42 \li \a m43 \li \a m44
+ \endtable
+
+ Alternatively, the function may be called with a single argument
+ where that argument is a JavaScript array which contains the sixteen
+ matrix values.
+
+ Finally, the function may be called with no arguments and the resulting
+ matrix will be the identity matrix.
*/
ReturnedValue QtObject::method_matrix4x4(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -572,18 +591,19 @@ ReturnedValue QtObject::method_matrix4x4(const FunctionObject *b, const Value *,
}
/*!
-\qmlmethod color Qt::lighter(color baseColor, real factor)
-Returns a color lighter than \c baseColor by the \c factor provided.
+ \qmlmethod color Qt::lighter(color baseColor, real factor)
-If the factor is greater than 1.0, this functions returns a lighter color.
-Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
-the return color is darker, but we recommend using the Qt.darker() function for this purpose.
-If the factor is 0 or negative, the return value is unspecified.
+ Returns a color lighter than \a baseColor by the \a factor provided.
-The function converts the current RGB color to HSV, multiplies the value (V) component
-by factor and converts the color back to RGB.
+ If the factor is greater than 1.0, this functions returns a lighter color.
+ Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
+ the return color is darker, but we recommend using the Qt.darker() function for this purpose.
+ If the factor is 0 or negative, the return value is unspecified.
-If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
+ The function converts the current RGB color to HSV, multiplies the value (V) component
+ by factor and converts the color back to RGB.
+
+ If \a factor is not supplied, returns a color that is 50% lighter than \a baseColor (factor 1.5).
*/
ReturnedValue QtObject::method_lighter(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -610,19 +630,20 @@ ReturnedValue QtObject::method_lighter(const FunctionObject *b, const Value *, c
}
/*!
-\qmlmethod color Qt::darker(color baseColor, real factor)
-Returns a color darker than \c baseColor by the \c factor provided.
+ \qmlmethod color Qt::darker(color baseColor, real factor)
+
+ Returns a color darker than \a baseColor by the \a factor provided.
-If the factor is greater than 1.0, this function returns a darker color.
-Setting factor to 3.0 returns a color that has one-third the brightness.
-If the factor is less than 1.0, the return color is lighter, but we recommend using
-the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
-value is unspecified.
+ If the factor is greater than 1.0, this function returns a darker color.
+ Setting factor to 3.0 returns a color that has one-third the brightness.
+ If the factor is less than 1.0, the return color is lighter, but we recommend using
+ the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
+ value is unspecified.
-The function converts the current RGB color to HSV, divides the value (V) component
-by factor and converts the color back to RGB.
+ The function converts the current RGB color to HSV, divides the value (V) component
+ by factor and converts the color back to RGB.
-If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
+ If \a factor is not supplied, returns a color that is 50% darker than \a baseColor (factor 2.0).
*/
ReturnedValue QtObject::method_darker(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -650,7 +671,8 @@ ReturnedValue QtObject::method_darker(const FunctionObject *b, const Value *, co
/*!
\qmlmethod color Qt::tint(color baseColor, color tintColor)
- This function allows tinting one color with another.
+
+ This function allows tinting one color (\a baseColor) with another (\a tintColor).
The tint color should usually be mostly transparent, or you will not be
able to see the underlying color. The below example provides a slight red
@@ -670,7 +692,8 @@ ReturnedValue QtObject::method_darker(const FunctionObject *b, const Value *, co
\endqml
\image declarative-rect_tint.png
- Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
+ Tint is most useful when a subtle change is intended to be conveyed due to some event;
+ you can then use tinting to more effectively tune the visible color.
*/
ReturnedValue QtObject::method_tint(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -708,8 +731,8 @@ ReturnedValue QtObject::method_tint(const FunctionObject *b, const Value *, cons
/*!
\qmlmethod string Qt::formatDate(datetime date, variant format)
-Returns a string representation of \c date, optionally formatted according
-to \c format.
+Returns a string representation of \a date, optionally formatted according
+to \a format.
The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
property, a QDate, or QDateTime value. The \a format parameter may be any of
@@ -752,8 +775,8 @@ ReturnedValue QtObject::method_formatDate(const FunctionObject *b, const Value *
/*!
\qmlmethod string Qt::formatTime(datetime time, variant format)
-Returns a string representation of \c time, optionally formatted according to
-\c format.
+Returns a string representation of \a time, optionally formatted according to
+\a format.
The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
value. The \a format parameter may be any of the possible format values as
@@ -801,10 +824,10 @@ ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value *
/*!
\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
-Returns a string representation of \c datetime, optionally formatted according to
-\c format.
+Returns a string representation of \a dateTime, optionally formatted according to
+\a format.
-The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
+The \a dateTime parameter may be a JavaScript \c Date object, a \l{date}{date}
property, a QDate, QTime, or QDateTime value.
If \a format is not provided, \a dateTime is formatted using
@@ -921,8 +944,8 @@ ReturnedValue QtObject::method_formatDateTime(const FunctionObject *b, const Val
/*!
\qmlmethod bool Qt::openUrlExternally(url target)
- Attempts to open the specified \c target url in an external application, based on the user's
- desktop preferences. Returns true if it succeeds, and false otherwise.
+ Attempts to open the specified \a target url in an external application, based on the user's
+ desktop preferences. Returns \c true if it succeeds, \c false otherwise.
\warning A return value of \c true indicates that the application has successfully requested
the operating system to open the URL in an external application. The external application may
@@ -942,6 +965,7 @@ ReturnedValue QtObject::method_openUrlExternally(const FunctionObject *b, const
/*!
\qmlmethod url Qt::resolvedUrl(url url)
+
Returns \a url resolved relative to the URL of the caller.
*/
ReturnedValue QtObject::method_resolvedUrl(const FunctionObject *b, const Value *, const Value *argv, int argc)
@@ -967,6 +991,7 @@ ReturnedValue QtObject::method_resolvedUrl(const FunctionObject *b, const Value
/*!
\qmlmethod list<string> Qt::fontFamilies()
+
Returns a list of the font families available to the application.
*/
ReturnedValue QtObject::method_fontFamilies(const FunctionObject *b, const Value *, const Value *, int argc)
@@ -980,7 +1005,7 @@ ReturnedValue QtObject::method_fontFamilies(const FunctionObject *b, const Value
/*!
\qmlmethod string Qt::md5(data)
-Returns a hex string of the md5 hash of \c data.
+Returns a hex string of the md5 hash of \a data.
*/
ReturnedValue QtObject::method_md5(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -995,7 +1020,7 @@ ReturnedValue QtObject::method_md5(const FunctionObject *b, const Value *, const
/*!
\qmlmethod string Qt::btoa(data)
-Binary to ASCII - this function returns a base64 encoding of \c data.
+Binary to ASCII - this function returns a base64 encoding of \a data.
*/
ReturnedValue QtObject::method_btoa(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -1043,9 +1068,9 @@ ReturnedValue QtObject::method_quit(const FunctionObject *b, const Value *, cons
This function causes the QQmlEngine::exit(int) signal to be emitted.
Within the \l {Prototyping with qmlscene}, this causes the launcher application to exit
- the specified return code. To exit from the event loop with a specified return code when this
- method is called, a C++ application can connect the QQmlEngine::exit(int) signal
- to the QCoreApplication::exit(int) slot.
+ the specified return code (\a retCode). To exit from the event loop with a specified
+ return code when this method is called, a C++ application can connect the
+ QQmlEngine::exit(int) signal to the QCoreApplication::exit(int) slot.
\sa quit()
*/
@@ -1318,13 +1343,13 @@ ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Va
\qmlmethod Qt::locale(name)
Returns a JS object representing the locale with the specified
- name, which has the format "language[_territory][.codeset][@modifier]"
+ \a name, which has the format "language[_territory][.codeset][@modifier]"
or "C", where:
\list
- \li language is a lowercase, two-letter, ISO 639 language code,
- \li territory is an uppercase, two-letter, ISO 3166 country code,
- \li and codeset and modifier are ignored.
+ \li \c language is a lowercase, two-letter, ISO 639 language code,
+ \li \c territory is an uppercase, two-letter, ISO 3166 country code, and
+ \li \c codeset and \c modifier are ignored.
\endlist
If the string violates the locale format, or language is not a
@@ -1372,7 +1397,8 @@ DEFINE_OBJECT_VTABLE(QQmlBindingFunction);
/*!
\qmlmethod Qt::binding(function)
- Returns a JavaScript object representing a \l{Property Binding}{property binding}.
+ Returns a JavaScript object representing a \l{Property Binding}{property binding},
+ with a \a function that evaluates the binding.
There are two main use-cases for the function: firstly, to apply a
property binding imperatively from JavaScript code:
@@ -1941,30 +1967,32 @@ ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value
THROW_GENERIC_ERROR("qsTr(): third argument (n) must be a number");
QString context;
- if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
- QString path = ctxt->urlString();
- int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- int lastDot = path.lastIndexOf(QLatin1Char('.'));
- int length = lastDot - (lastSlash + 1);
- context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
- } else {
- CppStackFrame *frame = scope.engine->currentStackFrame;
- // The first non-empty source URL in the call stack determines the translation context.
- while (frame && context.isEmpty()) {
- if (CompiledData::CompilationUnitBase *baseUnit = frame->v4Function->compilationUnit) {
- const auto *unit = static_cast<const CompiledData::CompilationUnit *>(baseUnit);
- QString fileName = unit->fileName();
- QUrl url(unit->fileName());
- if (url.isValid() && url.isRelative()) {
- context = url.fileName();
- } else {
- context = QQmlFile::urlToLocalFileOrQrc(fileName);
- if (context.isEmpty() && fileName.startsWith(QLatin1String(":/")))
- context = fileName;
- }
- context = QFileInfo(context).baseName();
+ CppStackFrame *frame = scope.engine->currentStackFrame;
+ // The first non-empty source URL in the call stack determines the translation context.
+ while (frame && context.isEmpty()) {
+ if (CompiledData::CompilationUnitBase *baseUnit = frame->v4Function->compilationUnit) {
+ const auto *unit = static_cast<const CompiledData::CompilationUnit *>(baseUnit);
+ QString fileName = unit->fileName();
+ QUrl url(unit->fileName());
+ if (url.isValid() && url.isRelative()) {
+ context = url.fileName();
+ } else {
+ context = QQmlFile::urlToLocalFileOrQrc(fileName);
+ if (context.isEmpty() && fileName.startsWith(QLatin1String(":/")))
+ context = fileName;
}
- frame = frame->parent;
+ context = QFileInfo(context).baseName();
+ }
+ frame = frame->parent;
+ }
+
+ if (context.isEmpty()) {
+ if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
+ QString path = ctxt->urlString();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ int lastDot = path.lastIndexOf(QLatin1Char('.'));
+ int length = lastDot - (lastSlash + 1);
+ context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
}
}
diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp
index 5bf33d3602..6e925ba515 100644
--- a/src/qml/qmldirparser/qqmldirparser.cpp
+++ b/src/qml/qmldirparser/qqmldirparser.cpp
@@ -73,14 +73,6 @@ static bool parseVersion(const QString &str, int *major, int *minor)
return false;
}
-QQmlDirParser::QQmlDirParser() : _designerSupported(false)
-{
-}
-
-QQmlDirParser::~QQmlDirParser()
-{
-}
-
inline static void scanSpace(const QChar *&ch) {
while (ch->isSpace() && !ch->isNull() && *ch != QLatin1Char('\n'))
++ch;
diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h
index 37ca1ef2ce..c9d77532c8 100644
--- a/src/qml/qmldirparser/qqmldirparser_p.h
+++ b/src/qml/qmldirparser/qqmldirparser_p.h
@@ -64,9 +64,6 @@ class QQmlEngine;
class Q_QMLCOMPILER_PRIVATE_EXPORT QQmlDirParser
{
public:
- QQmlDirParser();
- ~QQmlDirParser();
-
bool parse(const QString &source);
bool hasError() const;
@@ -87,7 +84,7 @@ public:
struct Plugin
{
- Plugin() {}
+ Plugin() = default;
Plugin(const QString &name, const QString &path)
: name(name), path(path)
@@ -101,7 +98,7 @@ public:
struct Component
{
- Component() {}
+ Component() = default;
Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion)
: typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion),
@@ -120,7 +117,7 @@ public:
struct Script
{
- Script() {}
+ Script() = default;
Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion)
: nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion)
@@ -143,7 +140,7 @@ public:
struct TypeInfo
{
- TypeInfo() {}
+ TypeInfo() = default;
TypeInfo(const QString &fileName)
: fileName(fileName) {}
@@ -166,14 +163,14 @@ private:
QStringList _imports;
QList<Script> _scripts;
QList<Plugin> _plugins;
- bool _designerSupported;
+ bool _designerSupported = false;
QList<TypeInfo> _typeInfos;
QString _className;
};
-typedef QHash<QString,QQmlDirParser::Component> QQmlDirComponents;
-typedef QList<QQmlDirParser::Script> QQmlDirScripts;
-typedef QList<QQmlDirParser::Plugin> QQmlDirPlugins;
+using QQmlDirComponents = QHash<QString,QQmlDirParser::Component>;
+using QQmlDirScripts = QList<QQmlDirParser::Script>;
+using QQmlDirPlugins = QList<QQmlDirParser::Plugin>;
QDebug &operator<< (QDebug &, const QQmlDirParser::Component &);
QDebug &operator<< (QDebug &, const QQmlDirParser::Script &);
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 861243987f..921d60caa1 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -54,11 +54,14 @@
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
+#include <QtCore/qloggingcategory.h>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcBindingRemoval)
+
class QQmlBindPrivate : public QObjectPrivate
{
public:
@@ -72,13 +75,14 @@ public:
, restoreBinding(true)
, restoreValue(false)
, restoreModeExplicit(false)
+ , writingProperty(false)
{}
~QQmlBindPrivate() { }
QQmlNullableValue<bool> when;
QPointer<QObject> obj;
QString propName;
- QQmlNullableValue<QVariant> value;
+ QQmlNullableValue<QJSValue> value;
QQmlProperty prop;
QQmlAbstractBinding::Ptr prevBind;
QV4::PersistentValue v4Value;
@@ -90,6 +94,7 @@ public:
bool restoreBinding:1;
bool restoreValue:1;
bool restoreModeExplicit:1;
+ bool writingProperty: 1;
void validate(QObject *binding) const;
void clearPrev();
@@ -193,6 +198,13 @@ QQmlBind::~QQmlBind()
When the binding becomes inactive again, any direct bindings that were previously
set on the property will be restored.
+
+ \note By default, a previously set literal value is not restored when the Binding becomes
+ inactive. Rather, the last value set by the now inactive Binding is retained. You can customize
+ the restoration behavior for literal values as well as bindings using the \l restoreMode
+ property. The default will change in Qt 6.0.
+
+ \sa restoreMode
*/
bool QQmlBind::when() const
{
@@ -235,7 +247,7 @@ void QQmlBind::setObject(QObject *obj)
}
d->obj = obj;
if (d->componentComplete) {
- d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this));
+ setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
d->validate(this);
}
eval();
@@ -281,7 +293,7 @@ void QQmlBind::setProperty(const QString &p)
}
d->propName = p;
if (d->componentComplete) {
- d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this));
+ setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
d->validate(this);
}
eval();
@@ -293,13 +305,13 @@ void QQmlBind::setProperty(const QString &p)
The value to be set on the target object and property. This can be a
constant (which isn't very useful), or a bound expression.
*/
-QVariant QQmlBind::value() const
+QJSValue QQmlBind::value() const
{
Q_D(const QQmlBind);
return d->value.value;
}
-void QQmlBind::setValue(const QVariant &v)
+void QQmlBind::setValue(const QJSValue &v)
{
Q_D(QQmlBind);
d->value = v;
@@ -359,7 +371,8 @@ void QQmlBind::setDelayed(bool delayed)
\li Binding.RestoreBindingOrValue The original value is always restored.
\endlist
- The default value is Binding.RestoreBinding.
+ \warning The default value is Binding.RestoreBinding. This will change in
+ Qt 6.0 to Binding.RestoreBindingOrValue.
If you rely on any specific behavior regarding the restoration of plain
values when bindings get disabled you should migrate to explicitly set the
@@ -382,10 +395,10 @@ QQmlBind::RestorationMode QQmlBind::restoreMode() const
void QQmlBind::setRestoreMode(RestorationMode newMode)
{
Q_D(QQmlBind);
+ d->restoreModeExplicit = true;
if (newMode != restoreMode()) {
d->restoreValue = (newMode & RestoreValue);
d->restoreBinding = (newMode & RestoreBinding);
- d->restoreModeExplicit = true;
emit restoreModeChanged();
}
}
@@ -393,6 +406,19 @@ void QQmlBind::setRestoreMode(RestorationMode newMode)
void QQmlBind::setTarget(const QQmlProperty &p)
{
Q_D(QQmlBind);
+
+ if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) {
+ if (QObject *oldObject = d->prop.object()) {
+ QMetaProperty prop = oldObject->metaObject()->property(d->prop.index());
+ if (prop.hasNotifySignal()) {
+ QByteArray signal('2' + prop.notifySignal().methodSignature());
+ QObject::disconnect(oldObject, signal.constData(),
+ this, SLOT(targetValueChanged()));
+ }
+ }
+ p.connectNotifySignal(this, SLOT(targetValueChanged()));
+ }
+
d->prop = p;
}
@@ -407,7 +433,7 @@ void QQmlBind::componentComplete()
Q_D(QQmlBind);
d->componentComplete = true;
if (!d->prop.isValid()) {
- d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this));
+ setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
d->validate(this);
}
eval();
@@ -456,11 +482,23 @@ void QQmlBind::eval()
Q_ASSERT(vmemo);
vmemo->setVMEProperty(propPriv->core.coreIndex(), *d->v4Value.valueRef());
d->clearPrev();
+ } else if (!d->restoreModeExplicit) {
+ qmlWarning(this)
+ << "Not restoring previous value because restoreMode has not been set."
+ << "This behavior is deprecated."
+ << "In Qt < 6.0 the default is Binding.RestoreBinding."
+ << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue.";
}
} else if (d->prevIsVariant) {
if (d->restoreValue) {
d->prop.write(d->prevValue);
d->clearPrev();
+ } else if (!d->restoreModeExplicit) {
+ qmlWarning(this)
+ << "Not restoring previous value because restoreMode has not been set."
+ << "This behavior is deprecated."
+ << "In Qt < 6.0 the default is Binding.RestoreBinding."
+ << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue.";
}
}
return;
@@ -489,7 +527,34 @@ void QQmlBind::eval()
QQmlPropertyPrivate::removeBinding(d->prop);
}
- d->prop.write(d->value.value);
+ d->writingProperty = true;
+ d->prop.write(d->value.value.toVariant());
+ d->writingProperty = false;
+}
+
+void QQmlBind::targetValueChanged()
+{
+ Q_D(QQmlBind);
+ if (d->writingProperty)
+ return;
+
+ if (d->when.isValid() && !d->when)
+ return;
+
+ QUrl url;
+ quint16 line = 0;
+
+ const QQmlData *ddata = QQmlData::get(this, false);
+ if (ddata && ddata->outerContext) {
+ url = ddata->outerContext->url();
+ line = ddata->lineNumber;
+ }
+
+ qCInfo(lcBindingRemoval,
+ "The target property of the Binding element created at %s:%d was changed from "
+ "elsewhere. This does not overwrite the binding. The target property will still be "
+ "updated when the value of the Binding element changes.",
+ qPrintable(url.toString()), line);
}
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h
index 22007a3d25..c709224c23 100644
--- a/src/qml/types/qqmlbind_p.h
+++ b/src/qml/types/qqmlbind_p.h
@@ -75,12 +75,13 @@ private:
Q_INTERFACES(QQmlPropertyValueSource)
Q_PROPERTY(QObject *target READ object WRITE setObject)
Q_PROPERTY(QString property READ property WRITE setProperty)
- Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(QJSValue value READ value WRITE setValue)
Q_PROPERTY(bool when READ when WRITE setWhen)
Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION 8)
Q_PROPERTY(RestorationMode restoreMode READ restoreMode WRITE setRestoreMode
NOTIFY restoreModeChanged REVISION 14)
Q_ENUM(RestorationMode)
+ QML_NAMED_ELEMENT(Binding)
public:
QQmlBind(QObject *parent=nullptr);
@@ -95,8 +96,8 @@ public:
QString property() const;
void setProperty(const QString &);
- QVariant value() const;
- void setValue(const QVariant &);
+ QJSValue value() const;
+ void setValue(const QJSValue &);
bool delayed() const;
void setDelayed(bool);
@@ -115,6 +116,9 @@ protected:
private:
void prepareEval();
void eval();
+
+private Q_SLOTS:
+ void targetValueChanged();
};
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index 5d28e8e8be..7bf688cf75 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -71,6 +71,7 @@ class Q_AUTOTEST_EXPORT QQmlConnections : public QObject, public QQmlParserStatu
Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged REVISION 3)
Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
+ QML_NAMED_ELEMENT(Connections)
public:
QQmlConnections(QObject *parent=nullptr);
@@ -106,6 +107,13 @@ public:
void applyBindings(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
+// TODO: We won't need Connections to be a custom type anymore once we can drop the
+// automatic signal handler inference from undeclared properties.
+template<>
+inline QQmlCustomParser *qmlCreateCustomParser<QQmlConnections>()
+{
+ return new QQmlConnectionsParser;
+}
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmltimer_p.h b/src/qml/types/qqmltimer_p.h
index 0160e97a2f..0cd93e4659 100644
--- a/src/qml/types/qqmltimer_p.h
+++ b/src/qml/types/qqmltimer_p.h
@@ -72,6 +72,7 @@ class Q_QML_PRIVATE_EXPORT QQmlTimer : public QObject, public QQmlParserStatus
Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating NOTIFY repeatChanged)
Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged)
Q_PROPERTY(QObject *parent READ parent CONSTANT)
+ QML_NAMED_ELEMENT(Timer)
public:
QQmlTimer(QObject *parent=nullptr);
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp
index 3f78ca6b69..82f048d9d9 100644
--- a/src/qml/util/qqmlpropertymap.cpp
+++ b/src/qml/util/qqmlpropertymap.cpp
@@ -180,6 +180,10 @@ int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *valu
\note When deriving a class from QQmlPropertyMap, use the
\l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)} {protected two-argument constructor}
which ensures that the class is correctly registered with the Qt \l {Meta-Object System}.
+
+ \note The QMetaObject of a QQmlPropertyMap is dynamically generated and modified.
+ Operations on that meta object are not thread safe, so applications need to take
+ care to explicitly synchronize access to the meta object.
*/
/*!
diff --git a/src/qmldebug/qqmldebugconnection.cpp b/src/qmldebug/qqmldebugconnection.cpp
index 4e087ee6db..15c56fc20d 100644
--- a/src/qmldebug/qqmldebugconnection.cpp
+++ b/src/qmldebug/qqmldebugconnection.cpp
@@ -205,14 +205,14 @@ void QQmlDebugConnection::protocolReadyRead()
QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter) {
- const QString pluginName = iter.key();
- QQmlDebugClient::State newSate = QQmlDebugClient::Unavailable;
+ const QString &pluginName = iter.key();
+ QQmlDebugClient::State newState = QQmlDebugClient::Unavailable;
if (d->serverPlugins.contains(pluginName))
- newSate = QQmlDebugClient::Enabled;
+ newState = QQmlDebugClient::Enabled;
if (oldServerPlugins.contains(pluginName)
!= d->serverPlugins.contains(pluginName)) {
- iter.value()->stateChanged(newSate);
+ iter.value()->stateChanged(newState);
}
}
} else {
@@ -223,9 +223,10 @@ void QQmlDebugConnection::protocolReadyRead()
if (iter == d->plugins.end()) {
// We can get more messages for plugins we have removed because it takes time to
// send the advertisement message but the removal is instant locally.
- if (!d->removedPlugins.contains(name))
+ if (!d->removedPlugins.contains(name)) {
qWarning() << "QQmlDebugConnection: Message received for missing plugin"
<< name;
+ }
} else {
QQmlDebugClient *client = *iter;
QByteArray message;
@@ -307,7 +308,7 @@ void QQmlDebugConnection::close()
bool QQmlDebugConnection::waitForConnected(int msecs)
{
Q_D(QQmlDebugConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ auto socket = qobject_cast<QAbstractSocket*>(d->device);
if (!socket) {
if (!d->server || (!d->server->hasPendingConnections() &&
!d->server->waitForNewConnection(msecs)))
@@ -324,7 +325,7 @@ bool QQmlDebugConnection::waitForConnected(int msecs)
QQmlDebugClient *QQmlDebugConnection::client(const QString &name) const
{
Q_D(const QQmlDebugConnection);
- return d->plugins.value(name, 0);
+ return d->plugins.value(name, nullptr);
}
bool QQmlDebugConnection::addClient(const QString &name, QQmlDebugClient *client)
@@ -371,9 +372,9 @@ bool QQmlDebugConnection::sendMessage(const QString &name, const QByteArray &mes
void QQmlDebugConnectionPrivate::flush()
{
- if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(device))
+ if (auto socket = qobject_cast<QAbstractSocket *>(device))
socket->flush();
- else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(device))
+ else if (auto socket = qobject_cast<QLocalSocket *>(device))
socket->flush();
}
@@ -382,7 +383,7 @@ void QQmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
Q_D(QQmlDebugConnection);
if (d->gotHello)
close();
- QTcpSocket *socket = new QTcpSocket(this);
+ auto socket = new QTcpSocket(this);
d->device = socket;
d->createProtocol();
connect(socket, &QAbstractSocket::disconnected, this, &QQmlDebugConnection::socketDisconnected);
@@ -430,8 +431,8 @@ public:
}
signals:
- void socketError(QAbstractSocket::SocketError error);
- void socketStateChanged(QAbstractSocket::SocketState state);
+ void socketError(QAbstractSocket::SocketError);
+ void socketStateChanged(QAbstractSocket::SocketState);
};
void QQmlDebugConnection::newConnection()
@@ -443,7 +444,7 @@ void QQmlDebugConnection::newConnection()
d->device = socket;
d->createProtocol();
connect(socket, &QLocalSocket::disconnected, this, &QQmlDebugConnection::socketDisconnected);
- LocalSocketSignalTranslator *translator = new LocalSocketSignalTranslator(socket);
+ auto translator = new LocalSocketSignalTranslator(socket);
connect(translator, &LocalSocketSignalTranslator::socketError,
this, &QQmlDebugConnection::socketError);
diff --git a/src/qmldebug/qqmldebugconnection_p.h b/src/qmldebug/qqmldebugconnection_p.h
index ad9376886c..5abdd2943b 100644
--- a/src/qmldebug/qqmldebugconnection_p.h
+++ b/src/qmldebug/qqmldebugconnection_p.h
@@ -61,7 +61,6 @@ class QQmlDebugConnectionPrivate;
class QQmlDebugConnection : public QObject
{
Q_OBJECT
- Q_DISABLE_COPY(QQmlDebugConnection)
Q_DECLARE_PRIVATE(QQmlDebugConnection)
public:
QQmlDebugConnection(QObject *parent = nullptr);
diff --git a/src/qmldebug/qqmlenginedebugclient.cpp b/src/qmldebug/qqmlenginedebugclient.cpp
index 50f8deb087..0ca3f573d9 100644
--- a/src/qmldebug/qqmlenginedebugclient.cpp
+++ b/src/qmldebug/qqmlenginedebugclient.cpp
@@ -33,14 +33,14 @@ QT_BEGIN_NAMESPACE
struct QQmlObjectData {
QUrl url;
- int lineNumber = -1;
- int columnNumber = -1;
+ qint32 lineNumber = -1;
+ qint32 columnNumber = -1;
QString idString;
QString objectName;
QString objectType;
- int objectId = -1;
- int contextId = -1;
- int parentId = -1;
+ qint32 objectId = -1;
+ qint32 contextId = -1;
+ qint32 parentId = -1;
};
QPacket &operator>>(QPacket &ds, QQmlObjectData &data)
@@ -63,10 +63,10 @@ struct QQmlObjectProperty {
QPacket &operator>>(QPacket &ds, QQmlObjectProperty &data)
{
- int type;
+ qint32 type;
ds >> type >> data.name >> data.value >> data.valueTypeName
>> data.binding >> data.hasNotifySignal;
- data.type = (QQmlObjectProperty::Type)type;
+ data.type = QQmlObjectProperty::Type(type);
return ds;
}
@@ -81,10 +81,10 @@ QQmlEngineDebugClientPrivate::QQmlEngineDebugClientPrivate(QQmlDebugConnection *
}
-quint32 QQmlEngineDebugClient::addWatch(
+qint32 QQmlEngineDebugClient::addWatch(
const QQmlEngineDebugPropertyReference &property, bool *success)
{
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -97,19 +97,19 @@ quint32 QQmlEngineDebugClient::addWatch(
return id;
}
-quint32 QQmlEngineDebugClient::addWatch(
+qint32 QQmlEngineDebugClient::addWatch(
const QQmlEngineDebugContextReference &, const QString &, bool *success)
{
*success = false;
qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
- return 0;
+ return -1;
}
-quint32 QQmlEngineDebugClient::addWatch(
+qint32 QQmlEngineDebugClient::addWatch(
const QQmlEngineDebugObjectReference &object, const QString &expr,
bool *success)
{
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -121,10 +121,10 @@ quint32 QQmlEngineDebugClient::addWatch(
return id;
}
-quint32 QQmlEngineDebugClient::addWatch(
+qint32 QQmlEngineDebugClient::addWatch(
const QQmlEngineDebugObjectReference &object, bool *success)
{
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -136,15 +136,15 @@ quint32 QQmlEngineDebugClient::addWatch(
return id;
}
-quint32 QQmlEngineDebugClient::addWatch(
+qint32 QQmlEngineDebugClient::addWatch(
const QQmlEngineDebugFileReference &, bool *success)
{
*success = false;
qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
- return 0;
+ return -1;
}
-void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success)
+void QQmlEngineDebugClient::removeWatch(qint32 id, bool *success)
{
*success = false;
if (state() == QQmlDebugClient::Enabled) {
@@ -155,11 +155,11 @@ void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success)
}
}
-quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success)
+qint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success)
{
Q_D(QQmlEngineDebugClient);
d->engines.clear();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -171,12 +171,12 @@ quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success)
return id;
}
-quint32 QQmlEngineDebugClient::queryRootContexts(
+qint32 QQmlEngineDebugClient::queryRootContexts(
const QQmlEngineDebugEngineReference &engine, bool *success)
{
Q_D(QQmlEngineDebugClient);
d->rootContext = QQmlEngineDebugContextReference();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled && engine.debugId != -1) {
id = getId();
@@ -188,12 +188,12 @@ quint32 QQmlEngineDebugClient::queryRootContexts(
return id;
}
-quint32 QQmlEngineDebugClient::queryObject(
+qint32 QQmlEngineDebugClient::queryObject(
const QQmlEngineDebugObjectReference &object, bool *success)
{
Q_D(QQmlEngineDebugClient);
d->object = QQmlEngineDebugObjectReference();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
id = getId();
@@ -205,12 +205,12 @@ quint32 QQmlEngineDebugClient::queryObject(
return id;
}
-quint32 QQmlEngineDebugClient::queryObjectsForLocation(
- const QString &file, int lineNumber, int columnNumber, bool *success)
+qint32 QQmlEngineDebugClient::queryObjectsForLocation(
+ const QString &file, qint32 lineNumber, qint32 columnNumber, bool *success)
{
Q_D(QQmlEngineDebugClient);
d->objects.clear();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -223,12 +223,12 @@ quint32 QQmlEngineDebugClient::queryObjectsForLocation(
return id;
}
-quint32 QQmlEngineDebugClient::queryObjectRecursive(
+qint32 QQmlEngineDebugClient::queryObjectRecursive(
const QQmlEngineDebugObjectReference &object, bool *success)
{
Q_D(QQmlEngineDebugClient);
d->object = QQmlEngineDebugObjectReference();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
id = getId();
@@ -240,12 +240,12 @@ quint32 QQmlEngineDebugClient::queryObjectRecursive(
return id;
}
-quint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &file,
- int lineNumber, int columnNumber, bool *success)
+qint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &file,
+ qint32 lineNumber, qint32 columnNumber, bool *success)
{
Q_D(QQmlEngineDebugClient);
d->objects.clear();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -258,12 +258,12 @@ quint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &f
return id;
}
-quint32 QQmlEngineDebugClient::queryExpressionResult(
- int objectDebugId, const QString &expr, bool *success)
+qint32 QQmlEngineDebugClient::queryExpressionResult(
+ qint32 objectDebugId, const QString &expr, bool *success)
{
Q_D(QQmlEngineDebugClient);
d->exprResult = QVariant();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -276,12 +276,12 @@ quint32 QQmlEngineDebugClient::queryExpressionResult(
return id;
}
-quint32 QQmlEngineDebugClient::queryExpressionResultBC(
- int objectDebugId, const QString &expr, bool *success)
+qint32 QQmlEngineDebugClient::queryExpressionResultBC(
+ qint32 objectDebugId, const QString &expr, bool *success)
{
Q_D(QQmlEngineDebugClient);
d->exprResult = QVariant();
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled) {
id = getId();
@@ -293,15 +293,15 @@ quint32 QQmlEngineDebugClient::queryExpressionResultBC(
return id;
}
-quint32 QQmlEngineDebugClient::setBindingForObject(
- int objectDebugId,
+qint32 QQmlEngineDebugClient::setBindingForObject(
+ qint32 objectDebugId,
const QString &propertyName,
const QVariant &bindingExpression,
bool isLiteralValue,
- const QString &source, int line,
+ const QString &source, qint32 line,
bool *success)
{
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
id = getId();
@@ -314,12 +314,12 @@ quint32 QQmlEngineDebugClient::setBindingForObject(
return id;
}
-quint32 QQmlEngineDebugClient::resetBindingForObject(
- int objectDebugId,
+qint32 QQmlEngineDebugClient::resetBindingForObject(
+ qint32 objectDebugId,
const QString &propertyName,
bool *success)
{
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
id = getId();
@@ -331,11 +331,11 @@ quint32 QQmlEngineDebugClient::resetBindingForObject(
return id;
}
-quint32 QQmlEngineDebugClient::setMethodBody(
- int objectDebugId, const QString &methodName,
+qint32 QQmlEngineDebugClient::setMethodBody(
+ qint32 objectDebugId, const QString &methodName,
const QString &methodBody, bool *success)
{
- quint32 id = -1;
+ qint32 id = -1;
*success = false;
if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
id = getId();
@@ -366,19 +366,19 @@ void QQmlEngineDebugClient::decode(QPacket &ds,
if (simple)
return;
- int childCount;
+ qint32 childCount;
bool recur;
ds >> childCount >> recur;
- for (int ii = 0; ii < childCount; ++ii) {
+ for (qint32 ii = 0; ii < childCount; ++ii) {
o.children.append(QQmlEngineDebugObjectReference());
decode(ds, o.children.last(), !recur);
}
- int propCount;
+ qint32 propCount;
ds >> propCount;
- for (int ii = 0; ii < propCount; ++ii) {
+ for (qint32 ii = 0; ii < propCount; ++ii) {
QQmlObjectProperty data;
ds >> data;
QQmlEngineDebugPropertyReference prop;
@@ -414,9 +414,9 @@ void QQmlEngineDebugClient::decode(QPacket &ds,
QList<QQmlEngineDebugObjectReference> &o,
bool simple)
{
- int count;
+ qint32 count;
ds >> count;
- for (int i = 0; i < count; i++) {
+ for (qint32 i = 0; i < count; i++) {
QQmlEngineDebugObjectReference obj;
decode(ds, obj, simple);
o << obj;
@@ -464,18 +464,18 @@ void QQmlEngineDebugClient::decode(QPacket &ds,
{
ds >> c.name >> c.debugId;
- int contextCount;
+ qint32 contextCount;
ds >> contextCount;
- for (int ii = 0; ii < contextCount; ++ii) {
+ for (qint32 ii = 0; ii < contextCount; ++ii) {
c.contexts.append(QQmlEngineDebugContextReference());
decode(ds, c.contexts.last());
}
- int objectCount;
+ qint32 objectCount;
ds >> objectCount;
- for (int ii = 0; ii < objectCount; ++ii) {
+ for (qint32 ii = 0; ii < objectCount; ++ii) {
QQmlEngineDebugObjectReference obj;
decode(ds, obj, true);
@@ -490,18 +490,18 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
d->valid = false;
QPacket ds(connection()->currentDataStreamVersion(), data);
- int queryId;
+ qint32 queryId;
QByteArray type;
ds >> type >> queryId;
//qDebug() << "QQmlEngineDebugPrivate::message()" << type;
if (type == "LIST_ENGINES_R") {
- int count;
+ qint32 count;
ds >> count;
d->engines.clear();
- for (int ii = 0; ii < count; ++ii) {
+ for (qint32 ii = 0; ii < count; ++ii) {
QQmlEngineDebugEngineReference eng;
ds >> eng.name;
ds >> eng.debugId;
@@ -532,7 +532,7 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
ds >> d->valid;
} else if (type == "UPDATE_WATCH") {
- int debugId;
+ qint32 debugId;
QByteArray name;
QVariant value;
ds >> debugId >> name >> value;
@@ -540,7 +540,9 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
return;
} else if (type == "OBJECT_CREATED") {
- int engineId, objectId, parentId;
+ qint32 engineId;
+ qint32 objectId;
+ qint32 parentId;
ds >> engineId >> objectId >> parentId;
emit newObject(objectId);
return;
@@ -557,7 +559,7 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
}
-quint32 QQmlEngineDebugClient::getId()
+qint32 QQmlEngineDebugClient::getId()
{
Q_D(QQmlEngineDebugClient);
return d->nextId++;
diff --git a/src/qmldebug/qqmlenginedebugclient_p.h b/src/qmldebug/qqmlenginedebugclient_p.h
index 4a9cc3a020..0a01f2eac5 100644
--- a/src/qmldebug/qqmlenginedebugclient_p.h
+++ b/src/qmldebug/qqmlenginedebugclient_p.h
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
struct QQmlEngineDebugPropertyReference
{
- int objectDebugId = -1;
+ qint32 objectDebugId = -1;
QString name;
QVariant value;
QString valueTypeName;
@@ -61,25 +61,25 @@ struct QQmlEngineDebugPropertyReference
struct QQmlEngineDebugFileReference
{
QUrl url;
- int lineNumber = -1;
- int columnNumber = -1;
+ qint32 lineNumber = -1;
+ qint32 columnNumber = -1;
};
struct QQmlEngineDebugObjectReference
{
- int debugId = -1;
+ qint32 debugId = -1;
QString className;
QString idString;
QString name;
QQmlEngineDebugFileReference source;
- int contextDebugId = -1;
+ qint32 contextDebugId = -1;
QList<QQmlEngineDebugPropertyReference> properties;
QList<QQmlEngineDebugObjectReference> children;
};
struct QQmlEngineDebugContextReference
{
- int debugId = -1;
+ qint32 debugId = -1;
QString name;
QList<QQmlEngineDebugObjectReference> objects;
QList<QQmlEngineDebugContextReference> contexts;
@@ -87,7 +87,7 @@ struct QQmlEngineDebugContextReference
struct QQmlEngineDebugEngineReference
{
- int debugId = -1;
+ qint32 debugId = -1;
QString name;
};
@@ -100,46 +100,46 @@ class QQmlEngineDebugClient : public QQmlDebugClient
public:
explicit QQmlEngineDebugClient(QQmlDebugConnection *conn);
- quint32 addWatch(const QQmlEngineDebugPropertyReference &,
- bool *success);
- quint32 addWatch(const QQmlEngineDebugContextReference &, const QString &,
- bool *success);
- quint32 addWatch(const QQmlEngineDebugObjectReference &, const QString &,
- bool *success);
- quint32 addWatch(const QQmlEngineDebugObjectReference &,
- bool *success);
- quint32 addWatch(const QQmlEngineDebugFileReference &,
+ qint32 addWatch(const QQmlEngineDebugPropertyReference &,
+ bool *success);
+ qint32 addWatch(const QQmlEngineDebugContextReference &, const QString &,
+ bool *success);
+ qint32 addWatch(const QQmlEngineDebugObjectReference &, const QString &,
+ bool *success);
+ qint32 addWatch(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ qint32 addWatch(const QQmlEngineDebugFileReference &,
bool *success);
- void removeWatch(quint32 watch, bool *success);
-
- quint32 queryAvailableEngines(bool *success);
- quint32 queryRootContexts(const QQmlEngineDebugEngineReference &,
- bool *success);
- quint32 queryObject(const QQmlEngineDebugObjectReference &,
- bool *success);
- quint32 queryObjectsForLocation(const QString &file,
- int lineNumber, int columnNumber, bool *success);
- quint32 queryObjectRecursive(const QQmlEngineDebugObjectReference &,
+ void removeWatch(qint32 watch, bool *success);
+
+ qint32 queryAvailableEngines(bool *success);
+ qint32 queryRootContexts(const QQmlEngineDebugEngineReference &,
+ bool *success);
+ qint32 queryObject(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ qint32 queryObjectsForLocation(const QString &file,
+ qint32 lineNumber, qint32 columnNumber, bool *success);
+ qint32 queryObjectRecursive(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ qint32 queryObjectsForLocationRecursive(const QString &file,
+ qint32 lineNumber, qint32 columnNumber, bool *success);
+ qint32 queryExpressionResult(qint32 objectDebugId,
+ const QString &expr,
+ bool *success);
+ qint32 queryExpressionResultBC(qint32 objectDebugId,
+ const QString &expr,
bool *success);
- quint32 queryObjectsForLocationRecursive(const QString &file,
- int lineNumber, int columnNumber, bool *success);
- quint32 queryExpressionResult(int objectDebugId,
- const QString &expr,
- bool *success);
- quint32 queryExpressionResultBC(int objectDebugId,
- const QString &expr,
- bool *success);
- quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
- const QVariant &bindingExpression,
- bool isLiteralValue,
- const QString &source, int line, bool *success);
- quint32 resetBindingForObject(int objectDebugId,
- const QString &propertyName, bool *success);
- quint32 setMethodBody(int objectDebugId, const QString &methodName,
- const QString &methodBody, bool *success);
-
- quint32 getId();
+ qint32 setBindingForObject(qint32 objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ const QString &source, qint32 line, bool *success);
+ qint32 resetBindingForObject(qint32 objectDebugId,
+ const QString &propertyName, bool *success);
+ qint32 setMethodBody(qint32 objectDebugId, const QString &methodName,
+ const QString &methodBody, bool *success);
+
+ qint32 getId();
void decode(QPacket &ds, QQmlEngineDebugContextReference &);
void decode(QPacket &ds, QQmlEngineDebugObjectReference &, bool simple);
@@ -153,7 +153,7 @@ public:
bool valid() const;
signals:
- void newObject(int objectId);
+ void newObject(qint32 objectId);
void valueChanged(QByteArray,QVariant);
void result();
diff --git a/src/qmldebug/qqmlenginedebugclient_p_p.h b/src/qmldebug/qqmlenginedebugclient_p_p.h
index 7c992ad3ab..b73da15e9d 100644
--- a/src/qmldebug/qqmlenginedebugclient_p_p.h
+++ b/src/qmldebug/qqmlenginedebugclient_p_p.h
@@ -62,7 +62,7 @@ class QQmlEngineDebugClientPrivate : public QQmlDebugClientPrivate
public:
QQmlEngineDebugClientPrivate(QQmlDebugConnection *connection);
- quint32 nextId = 0;
+ qint32 nextId = 0;
bool valid = false;
QList<QQmlEngineDebugEngineReference> engines;
QQmlEngineDebugContextReference rootContext;
diff --git a/src/qmlmodels/doc/qtqmlmodels.qdocconf b/src/qmlmodels/doc/qtqmlmodels.qdocconf
new file mode 100644
index 0000000000..a4153f4a53
--- /dev/null
+++ b/src/qmlmodels/doc/qtqmlmodels.qdocconf
@@ -0,0 +1,37 @@
+include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+include($QT_INSTALL_DOCS/config/exampleurl-qtdeclarative.qdocconf)
+
+project = QtQmlModels
+description = Qt Qml Models Reference Documentation
+version = $QT_VERSION
+moduleheader = QtQmlModels
+qhp.projects = QtQmlModels
+
+qhp.QtQmlModels.file = qtqmlmodels.qhp
+qhp.QtQmlModels.namespace = org.qt-project.qtqmlmodels.$QT_VERSION_TAG
+qhp.QtQmlModels.virtualFolder = qtqmlmodels
+qhp.QtQmlModels.indexRoot =
+
+qhp.QtQmlModels.filterAttributes = qtqmlmodels $QT_VERSION qtrefdoc
+qhp.QtQmlModels.customFilters.Qt.name = QtQmlModels $QT_VERSION
+qhp.QtQmlModels.customFilters.Qt.filterAttributes = qtqmlmodels $QT_VERSION
+
+qhp.QtQmlModels.title = QML Types
+qhp.QtQmlModels.indexTitle = Qt QML Models QML Types
+qhp.QtQmlModels.selectors = qmlclass
+qhp.QtQmlModels.sortPages = true
+
+tagfile = qtqmlmodels.tags
+
+depends += qtcore qtqml qtdoc
+
+headerdirs += ..
+
+sourcedirs += .. \
+ ../../imports/models
+
+exampledirs += ../../../examples/qml \
+ ../ \
+ snippets
+
+navigation.qmltypespage = "Qt Qml Models QML Types"
diff --git a/src/qml/doc/snippets/delegatemodel/delegatemodel.qml b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodel.qml
index 1a7baa6b1e..1a7baa6b1e 100644
--- a/src/qml/doc/snippets/delegatemodel/delegatemodel.qml
+++ b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodel.qml
diff --git a/src/qml/doc/snippets/delegatemodel/delegatemodel_rootindex/main.cpp b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodel_rootindex/main.cpp
index a56eb69616..a56eb69616 100644
--- a/src/qml/doc/snippets/delegatemodel/delegatemodel_rootindex/main.cpp
+++ b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodel_rootindex/main.cpp
diff --git a/src/qml/doc/snippets/delegatemodel/delegatemodel_rootindex/view.qml b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodel_rootindex/view.qml
index 2e17eed8f0..2e17eed8f0 100644
--- a/src/qml/doc/snippets/delegatemodel/delegatemodel_rootindex/view.qml
+++ b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodel_rootindex/view.qml
diff --git a/src/qml/doc/snippets/delegatemodel/delegatemodelgroup.qml b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodelgroup.qml
index 8562deeeda..8562deeeda 100644
--- a/src/qml/doc/snippets/delegatemodel/delegatemodelgroup.qml
+++ b/src/qmlmodels/doc/snippets/delegatemodel/delegatemodelgroup.qml
diff --git a/src/qml/doc/snippets/package/Delegate.qml b/src/qmlmodels/doc/snippets/package/Delegate.qml
index 7c73f35c3d..7c73f35c3d 100644
--- a/src/qml/doc/snippets/package/Delegate.qml
+++ b/src/qmlmodels/doc/snippets/package/Delegate.qml
diff --git a/src/qml/doc/snippets/package/view.qml b/src/qmlmodels/doc/snippets/package/view.qml
index 311cc3be8e..311cc3be8e 100644
--- a/src/qml/doc/snippets/package/view.qml
+++ b/src/qmlmodels/doc/snippets/package/view.qml
diff --git a/src/qml/doc/snippets/qml/listmodel/listelements.qml b/src/qmlmodels/doc/snippets/qml/listmodel/listelements.qml
index 12146c1420..12146c1420 100644
--- a/src/qml/doc/snippets/qml/listmodel/listelements.qml
+++ b/src/qmlmodels/doc/snippets/qml/listmodel/listelements.qml
diff --git a/src/qml/doc/snippets/qml/listmodel/listmodel-modify.qml b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel-modify.qml
index f293eff8ec..f293eff8ec 100644
--- a/src/qml/doc/snippets/qml/listmodel/listmodel-modify.qml
+++ b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel-modify.qml
diff --git a/src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel-nested.qml
index 8c193d6a5e..8c193d6a5e 100644
--- a/src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml
+++ b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel-nested.qml
diff --git a/src/qml/doc/snippets/qml/listmodel/listmodel-simple.qml b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel-simple.qml
index d07f868476..d07f868476 100644
--- a/src/qml/doc/snippets/qml/listmodel/listmodel-simple.qml
+++ b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel-simple.qml
diff --git a/src/qml/doc/snippets/qml/listmodel/listmodel.qml b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel.qml
index c2a69d6e8f..c2a69d6e8f 100644
--- a/src/qml/doc/snippets/qml/listmodel/listmodel.qml
+++ b/src/qmlmodels/doc/snippets/qml/listmodel/listmodel.qml
diff --git a/src/qml/doc/snippets/qml/tablemodel/fruit-example-complex.qml b/src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-complex.qml
index 104a2209d7..104a2209d7 100644
--- a/src/qml/doc/snippets/qml/tablemodel/fruit-example-complex.qml
+++ b/src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-complex.qml
diff --git a/src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml b/src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml
index d3f6176c70..d3f6176c70 100644
--- a/src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml
+++ b/src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml
diff --git a/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml b/src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
index f51c1818c3..f51c1818c3 100644
--- a/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
+++ b/src/qmlmodels/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
diff --git a/src/qmlmodels/qmlmodels.pro b/src/qmlmodels/qmlmodels.pro
index 7d1d9bdf67..1d733f5bdb 100644
--- a/src/qmlmodels/qmlmodels.pro
+++ b/src/qmlmodels/qmlmodels.pro
@@ -1,6 +1,8 @@
TARGET = QtQmlModels
QT = core-private qml-private
+QMAKE_DOCS = $$PWD/doc/qtqmlmodels.qdocconf
+
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FOREACH
HEADERS += \
diff --git a/src/qmlmodels/qqmldelegatecomponent.cpp b/src/qmlmodels/qqmldelegatecomponent.cpp
index ccb0d60053..cc3b38ec93 100644
--- a/src/qmlmodels/qqmldelegatecomponent.cpp
+++ b/src/qmlmodels/qqmldelegatecomponent.cpp
@@ -59,19 +59,6 @@ QVariant QQmlAbstractDelegateComponent::value(QQmlAdaptorModel *adaptorModel, in
}
/*!
- \qmlmodule Qt.labs.qmlmodels 1.0
- \title Qt Labs QML Models - QML Types
- \ingroup qmlmodules
- \brief The Qt Labs QML Models module provides various model-related types for use with views.
-
- To use this module, import the module with the following line:
-
- \qml
- import Qt.labs.qmlmodels 1.0
- \endqml
-*/
-
-/*!
\qmltype DelegateChoice
\instantiates QQmlDelegateChoice
\inqmlmodule Qt.labs.qmlmodels
diff --git a/src/qmlmodels/qqmldelegatecomponent_p.h b/src/qmlmodels/qqmldelegatecomponent_p.h
index 1d20f0327b..86ad04d2e3 100644
--- a/src/qmlmodels/qqmldelegatecomponent_p.h
+++ b/src/qmlmodels/qqmldelegatecomponent_p.h
@@ -64,6 +64,9 @@ class QQmlAdaptorModel;
class Q_QMLMODELS_PRIVATE_EXPORT QQmlAbstractDelegateComponent : public QQmlComponent
{
Q_OBJECT
+ QML_NAMED_ELEMENT(AbstractDelegateComponent)
+ QML_UNCREATABLE("Cannot create instance of abstract class AbstractDelegateComponent.")
+
public:
QQmlAbstractDelegateComponent(QObject *parent = nullptr);
~QQmlAbstractDelegateComponent() override;
@@ -90,6 +93,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateChoice : public QObject
Q_PROPERTY(int column READ column WRITE setColumn NOTIFY columnChanged)
Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_CLASSINFO("DefaultProperty", "delegate")
+ QML_NAMED_ELEMENT(DelegateChoice)
public:
QVariant roleValue() const;
void setRoleValue(const QVariant &roleValue);
@@ -126,6 +130,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateChooser : public QQmlAbstractDelega
Q_PROPERTY(QString role READ role WRITE setRole NOTIFY roleChanged)
Q_PROPERTY(QQmlListProperty<QQmlDelegateChoice> choices READ choices CONSTANT)
Q_CLASSINFO("DefaultProperty", "choices")
+ QML_NAMED_ELEMENT(DelegateChooser)
public:
QString role() const { return m_role; }
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 6c80f4a3e5..2c3382c643 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -48,7 +48,6 @@
#include <private/qqmlchangeset_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlcomponent_p.h>
-#include <private/qqmlincubator_p.h>
#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
@@ -454,7 +453,8 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
}
if (d->m_delegate == delegate)
return;
- bool wasValid = d->m_delegate != nullptr;
+ if (d->m_complete)
+ _q_itemsRemoved(0, d->m_count);
d->m_delegate.setObject(delegate, this);
d->m_delegateValidated = false;
if (d->m_delegateChooser)
@@ -470,7 +470,11 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
[d](){ d->delegateChanged(); });
}
}
- d->delegateChanged(d->m_delegate, wasValid);
+ if (d->m_complete) {
+ _q_itemsInserted(0, d->adaptorModelCount());
+ d->requestMoreIfNecessary();
+ }
+ emit delegateChanged();
}
/*!
@@ -540,10 +544,10 @@ void QQmlDelegateModel::setRootIndex(const QVariant &root)
\qmlmethod QModelIndex QtQml.Models::DelegateModel::modelIndex(int index)
QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
+ QML only operates on list data. This function assists in using
tree models in QML.
- Returns a QModelIndex for the specified index.
+ Returns a QModelIndex for the specified \a index.
This value can be assigned to rootIndex.
\sa rootIndex
@@ -887,6 +891,117 @@ static bool isDoneIncubating(QQmlIncubator::Status status)
return status == QQmlIncubator::Ready || status == QQmlIncubator::Error;
}
+PropertyUpdater::PropertyUpdater(QObject *parent) :
+ QObject(parent) {}
+
+void PropertyUpdater::doUpdate()
+{
+ auto sender = QObject::sender();
+ auto mo = sender->metaObject();
+ auto signalIndex = QObject::senderSignalIndex();
+ ++updateCount;
+ // start at 0 instead of propertyOffset to handle properties from parent hierarchy
+ for (auto i = 0; i < mo->propertyCount() + mo->propertyOffset(); ++i) {
+ auto property = mo->property(i);
+ if (property.notifySignal().methodIndex() == signalIndex) {
+ // we synchronize between required properties and model rolenames by name
+ // that's why the QQmlProperty and the metaobject property must have the same name
+ QQmlProperty qmlProp(parent(), QString::fromLatin1(property.name()));
+ qmlProp.write(property.read(QObject::sender()));
+ return;
+ }
+ }
+}
+
+void PropertyUpdater::breakBinding()
+{
+ auto it = senderToConnection.find(QObject::senderSignalIndex());
+ if (it == senderToConnection.end())
+ return;
+ if (updateCount == 0) {
+ QObject::disconnect(*it);
+ QQmlError warning;
+ warning.setUrl(qmlContext(QObject::sender())->baseUrl());
+ auto signalName = QString::fromLatin1(QObject::sender()->metaObject()->method(QObject::senderSignalIndex()).name());
+ signalName.chop(sizeof("changed")-1);
+ QString propName = signalName;
+ propName[0] = propName[0].toLower();
+ warning.setDescription(QString::fromUtf8("Writing to \"%1\" broke the binding to the underlying model").arg(propName));
+ qmlWarning(this, warning);
+ senderToConnection.erase(it);
+ } else {
+ --updateCount;
+ }
+}
+
+void QQDMIncubationTask::initializeRequiredProperties(QQmlDelegateModelItem *modelItemToIncubate, QObject *object)
+{
+ auto incubatorPriv = QQmlIncubatorPrivate::get(this);
+ QQmlData *d = QQmlData::get(object);
+ auto contextData = d ? d->context : nullptr;
+ if (contextData) {
+ contextData->hasExtraObject = true;
+ contextData->extraObject = modelItemToIncubate;
+ }
+ if (incubatorPriv->hadRequiredProperties()) {
+ if (incubatorPriv->requiredProperties().empty())
+ return;
+ RequiredProperties &requiredProperties = incubatorPriv->requiredProperties();
+
+ auto qmlMetaObject = modelItemToIncubate->metaObject();
+ // if a required property was not in the model, it might still be a static property of the
+ // QQmlDelegateModelItem or one of its derived classes this is the case for index, row,
+ // column, model and more
+ // the most derived subclass of QQmlDelegateModelItem is QQmlDMAbstractModelData at depth 2,
+ // so 4 should be plenty
+ QVarLengthArray<const QMetaObject *, 4> mos;
+ // we first check the dynamic meta object for properties originating from the model
+ mos.push_back(qmlMetaObject); // contains abstractitemmodelproperties
+ auto delegateModelItemSubclassMO = qmlMetaObject->superClass();
+ mos.push_back(delegateModelItemSubclassMO);
+
+ while (strcmp(delegateModelItemSubclassMO->className(), modelItemToIncubate->staticMetaObject.className())) {
+ delegateModelItemSubclassMO = delegateModelItemSubclassMO->superClass();
+ mos.push_back(delegateModelItemSubclassMO);
+ }
+ if (proxiedObject)
+ mos.push_back(proxiedObject->metaObject());
+
+ auto updater = new PropertyUpdater(object);
+ for (const QMetaObject *mo : mos) {
+ for (int i = mo->propertyOffset(); i < mo->propertyCount() + mo->propertyOffset(); ++i) {
+ auto prop = mo->property(i);
+ if (!prop.name())
+ continue;
+ auto propName = QString::fromUtf8(prop.name());
+ bool wasInRequired = false;
+ QQmlProperty componentProp = QQmlComponentPrivate::removePropertyFromRequired(
+ object, propName, requiredProperties, &wasInRequired);
+ // only write to property if it was actually requested by the component
+ if (wasInRequired && prop.hasNotifySignal()) {
+ QMetaMethod changeSignal = prop.notifySignal();
+ static QMetaMethod updateSlot = PropertyUpdater::staticMetaObject.method(PropertyUpdater::staticMetaObject.indexOfSlot("doUpdate()"));
+ QMetaObject::Connection conn = QObject::connect(modelItemToIncubate, changeSignal, updater, updateSlot);
+ auto propIdx = object->metaObject()->indexOfProperty(propName.toUtf8());
+ QMetaMethod writeToPropSignal = object->metaObject()->property(propIdx).notifySignal();
+ updater->senderToConnection[writeToPropSignal.methodIndex()] = conn;
+ static QMetaMethod breakBinding = PropertyUpdater::staticMetaObject.method(PropertyUpdater::staticMetaObject.indexOfSlot("breakBinding()"));
+ componentProp.write(prop.read(modelItemToIncubate));
+ // the connection needs to established after the write,
+ // else the signal gets triggered by it and breakBinding will remove the connection
+ QObject::connect(object, writeToPropSignal, updater, breakBinding);
+ }
+ else if (wasInRequired) // we still have to write, even if there is no change signal
+ componentProp.write(prop.read(modelItemToIncubate));
+ }
+ }
+ } else {
+ modelItemToIncubate->contextData->contextObject = modelItemToIncubate;
+ if (proxiedObject)
+ proxyContext->contextObject = proxiedObject;
+ }
+}
+
void QQDMIncubationTask::statusChanged(Status status)
{
if (vdm) {
@@ -987,6 +1102,7 @@ void QQDMIncubationTask::setInitialState(QObject *o)
void QQmlDelegateModelPrivate::setInitialState(QQDMIncubationTask *incubationTask, QObject *o)
{
QQmlDelegateModelItem *cacheItem = incubationTask->incubating;
+ incubationTask->initializeRequiredProperties(incubationTask->incubating, o);
cacheItem->object = o;
if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
@@ -1053,7 +1169,6 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ
QQmlContextData *ctxt = new QQmlContextData;
ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_context.data()));
- ctxt->contextObject = cacheItem;
cacheItem->contextData = ctxt;
if (m_adaptorModel.hasProxyObject()) {
@@ -1062,7 +1177,8 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ
ctxt = new QQmlContextData;
ctxt->setParent(cacheItem->contextData, /*stronglyReferencedByParent*/true);
QObject *proxied = proxy->proxiedObject();
- ctxt->contextObject = proxied;
+ cacheItem->incubationTask->proxiedObject = proxied;
+ cacheItem->incubationTask->proxyContext = ctxt;
// We don't own the proxied object. We need to clear it if it goes away.
QObject::connect(proxied, &QObject::destroyed,
cacheItem, &QQmlDelegateModelItem::childContextObjectDestroyed);
@@ -2166,6 +2282,8 @@ QQmlDelegateModelItem *QQmlDelegateModelItem::dataForObject(QObject *object)
{
QQmlData *d = QQmlData::get(object);
QQmlContextData *context = d ? d->context : nullptr;
+ if (context && context->hasExtraObject)
+ return qobject_cast<QQmlDelegateModelItem *>(context->extraObject);
for (context = context ? context->parent : nullptr; context; context = context->parent) {
if (QQmlDelegateModelItem *cacheItem = qobject_cast<QQmlDelegateModelItem *>(
context->contextObject)) {
diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h
index 21eaef02e0..02904a71d7 100644
--- a/src/qmlmodels/qqmldelegatemodel_p.h
+++ b/src/qmlmodels/qqmldelegatemodel_p.h
@@ -77,7 +77,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, p
Q_DECLARE_PRIVATE(QQmlDelegateModel)
Q_PROPERTY(QVariant model READ model WRITE setModel)
- Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
Q_PROPERTY(QQmlDelegateModelGroup *items READ items CONSTANT) //TODO : worth renaming?
Q_PROPERTY(QQmlDelegateModelGroup *persistedItems READ persistedItems CONSTANT)
@@ -85,7 +85,11 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, p
Q_PROPERTY(QObject *parts READ parts CONSTANT)
Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
Q_CLASSINFO("DefaultProperty", "delegate")
+ QML_NAMED_ELEMENT(DelegateModel)
+ QML_ADDED_IN_MINOR_VERSION(1)
+ QML_ATTACHED(QQmlDelegateModelAttached)
Q_INTERFACES(QQmlParserStatus)
+
public:
QQmlDelegateModel();
QQmlDelegateModel(QQmlContext *, QObject *parent=nullptr);
@@ -136,6 +140,7 @@ Q_SIGNALS:
void filterGroupChanged();
void defaultGroupsChanged();
void rootIndexChanged();
+ void delegateChanged();
private Q_SLOTS:
void _q_itemsChanged(int index, int count, const QVector<int> &roles);
@@ -163,6 +168,8 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateModelGroup : public QObject
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(bool includeByDefault READ defaultInclude WRITE setDefaultInclude NOTIFY defaultIncludeChanged)
+ QML_NAMED_ELEMENT(DelegateModelGroup)
+ QML_ADDED_IN_MINOR_VERSION(1)
public:
QQmlDelegateModelGroup(QObject *parent = nullptr);
QQmlDelegateModelGroup(const QString &name, QQmlDelegateModel *model, int compositorType, QObject *parent = nullptr);
@@ -240,7 +247,6 @@ public:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQmlDelegateModel)
-QML_DECLARE_TYPEINFO(QQmlDelegateModel, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQmlDelegateModelGroup)
#endif // QQMLDATAMODEL_P_H
diff --git a/src/qmlmodels/qqmldelegatemodel_p_p.h b/src/qmlmodels/qqmldelegatemodel_p_p.h
index 92362b8876..06365a212f 100644
--- a/src/qmlmodels/qqmldelegatemodel_p_p.h
+++ b/src/qmlmodels/qqmldelegatemodel_p_p.h
@@ -201,11 +201,14 @@ public:
, incubating(nullptr)
, vdm(l) {}
+ void initializeRequiredProperties(QQmlDelegateModelItem *modelItemToIncubate, QObject* object);
void statusChanged(Status) override;
void setInitialState(QObject *) override;
QQmlDelegateModelItem *incubating = nullptr;
QQmlDelegateModelPrivate *vdm = nullptr;
+ QQmlContextData *proxyContext = nullptr;
+ QPointer<QObject> proxiedObject = nullptr; // the proxied object might disapear, so we use a QPointer instead of a raw one
int index[QQmlListCompositor::MaximumGroupCount];
};
@@ -445,6 +448,19 @@ private:
const int indexPropertyOffset;
};
+class PropertyUpdater : public QObject
+{
+ Q_OBJECT
+
+public:
+ PropertyUpdater(QObject *parent);
+ QHash<int, QMetaObject::Connection> senderToConnection;
+ int updateCount = 0;
+public Q_SLOTS:
+ void doUpdate();
+ void breakBinding();
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/qmlmodels/qqmlinstantiator.cpp b/src/qmlmodels/qqmlinstantiator.cpp
index af1b526e1d..f9d5762f6e 100644
--- a/src/qmlmodels/qqmlinstantiator.cpp
+++ b/src/qmlmodels/qqmlinstantiator.cpp
@@ -220,7 +220,8 @@ void QQmlInstantiatorPrivate::makeModel()
/*!
\qmltype Instantiator
\instantiates QQmlInstantiator
- \inqmlmodule QtQml
+ \inqmlmodule QtQml.Models
+ \ingroup qtquick-models
\brief Dynamically creates objects.
A Instantiator can be used to control the dynamic creation of objects, or to dynamically
@@ -231,6 +232,8 @@ void QQmlInstantiatorPrivate::makeModel()
can also be destroyed dynamically through other means, and the Instantiator will not recreate
them unless the properties of the Instantiator change.
+ \note Instantiator is part of QtQml.Models since version 2.14 and part of QtQml since
+ version 2.1. Importing Instantiator via QtQml is deprecated since Qt 5.14.
*/
QQmlInstantiator::QQmlInstantiator(QObject *parent)
: QObject(*(new QQmlInstantiatorPrivate), parent)
diff --git a/src/qmlmodels/qqmlinstantiator_p.h b/src/qmlmodels/qqmlinstantiator_p.h
index 87accc304f..9f6d816d18 100644
--- a/src/qmlmodels/qqmlinstantiator_p.h
+++ b/src/qmlmodels/qqmlinstantiator_p.h
@@ -72,6 +72,8 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlInstantiator : public QObject, public QQmlP
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(QObject *object READ object NOTIFY objectChanged)
Q_CLASSINFO("DefaultProperty", "delegate")
+ QML_NAMED_ELEMENT(Instantiator)
+ QML_ADDED_IN_MINOR_VERSION(1)
public:
QQmlInstantiator(QObject *parent = nullptr);
diff --git a/src/qmlmodels/qqmlitemmodels.qdoc b/src/qmlmodels/qqmlitemmodels.qdoc
index f6e1b0b1b9..2e12dbf656 100644
--- a/src/qmlmodels/qqmlitemmodels.qdoc
+++ b/src/qmlmodels/qqmlitemmodels.qdoc
@@ -62,7 +62,7 @@
\section1 QModelIndexList Type
- \l QModelIndexList is exposed in QML as a JavaScript array. Conversions are
+ QModelIndexList is exposed in QML as a JavaScript array. Conversions are
automatically made from and to C++. In fact, any JavaScript array can be
converted back to QModelIndexList, with non-QModelIndex objects replaced by
invalid \l{QModelIndex}es.
diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp
index 1cd089f454..e0a66e7170 100644
--- a/src/qmlmodels/qqmllistmodel.cpp
+++ b/src/qmlmodels/qqmllistmodel.cpp
@@ -634,7 +634,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
mo->updateValues(*roles);
}
-void ListModel::set(int elementIndex, QV4::Object *object)
+void ListModel::set(int elementIndex, QV4::Object *object, ListModel::SetElement reason)
{
if (!object)
return;
@@ -684,7 +684,7 @@ void ListModel::set(int elementIndex, QV4::Object *object)
} else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
if (r.type == ListLayout::Role::DateTime) {
- QDateTime dt = date->toQDateTime();;
+ QDateTime dt = date->toQDateTime();
e->setDateTimePropertyFast(r, dt);
}
} else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
@@ -699,9 +699,16 @@ void ListModel::set(int elementIndex, QV4::Object *object)
e->setVariantMapFast(role, o);
}
} else if (propertyValue->isNullOrUndefined()) {
- const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
- if (r)
- e->clearProperty(*r);
+ if (reason == SetElement::WasJustInserted) {
+ QQmlError err;
+ auto memberName = propertyName->toString(m_modelCache->engine())->toQString();
+ err.setDescription(QString::fromLatin1("%1 is %2. Adding an object with a %2 member does not create a role for it.").arg(memberName, propertyValue->isNull() ? QLatin1String("null") : QLatin1String("undefined")));
+ qmlWarning(nullptr, err);
+ } else {
+ const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
+ if (r)
+ e->clearProperty(*r);
+ }
}
}
}
@@ -725,13 +732,13 @@ QVector<std::function<void()>> ListModel::remove(int index, int count)
void ListModel::insert(int elementIndex, QV4::Object *object)
{
insertElement(elementIndex);
- set(elementIndex, object);
+ set(elementIndex, object, SetElement::WasJustInserted);
}
int ListModel::append(QV4::Object *object)
{
int elementIndex = appendElement();
- set(elementIndex, object);
+ set(elementIndex, object, SetElement::WasJustInserted);
return elementIndex;
}
@@ -1641,8 +1648,18 @@ PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *p
if (attrs)
*attrs = QV4::Attr_Data;
if (pd) {
+
QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index);
- pd->value = v4->fromVariant(value);
+ if (auto recursiveListModel = qvariant_cast<QQmlListModel*>(value)) {
+ auto size = recursiveListModel->count();
+ auto array = ScopedArrayObject{scope, v4->newArrayObject(size)};
+ for (auto i = 0; i < size; i++) {
+ array->arrayPut(i, QJSValuePrivate::convertedToValue(v4, recursiveListModel->get(i)));
+ }
+ pd->value = array;
+ } else {
+ pd->value = v4->fromVariant(value);
+ }
}
return roleName->toPropertyKey();
}
diff --git a/src/qmlmodels/qqmllistmodel_p.h b/src/qmlmodels/qqmllistmodel_p.h
index 10d67c1c6f..dc5063eb97 100644
--- a/src/qmlmodels/qqmllistmodel_p.h
+++ b/src/qmlmodels/qqmllistmodel_p.h
@@ -83,6 +83,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlListModel : public QAbstractListModel
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(bool dynamicRoles READ dynamicRoles WRITE setDynamicRoles)
Q_PROPERTY(QObject *agent READ agent CONSTANT REVISION(14))
+ QML_NAMED_ELEMENT(ListModel)
public:
QQmlListModel(QObject *parent=nullptr);
@@ -171,7 +172,8 @@ private:
// ### FIXME
class QQmlListElement : public QObject
{
-Q_OBJECT
+ Q_OBJECT
+ QML_NAMED_ELEMENT(ListElement)
};
class QQmlListModelParser : public QQmlCustomParser
@@ -201,6 +203,12 @@ private:
QString listElementTypeName;
};
+template<>
+inline QQmlCustomParser *qmlCreateCustomParser<QQmlListModel>()
+{
+ return new QQmlListModelParser;
+}
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQmlListModel)
diff --git a/src/qmlmodels/qqmllistmodel_p_p.h b/src/qmlmodels/qqmllistmodel_p_p.h
index a0d0e9ad89..2ad5158050 100644
--- a/src/qmlmodels/qqmllistmodel_p_p.h
+++ b/src/qmlmodels/qqmllistmodel_p_p.h
@@ -381,8 +381,10 @@ public:
return elements.count();
}
+ enum class SetElement {WasJustInserted, IsCurrentlyUpdated};
+
void set(int elementIndex, QV4::Object *object, QVector<int> *roles);
- void set(int elementIndex, QV4::Object *object);
+ void set(int elementIndex, QV4::Object *object, SetElement reason = SetElement::IsCurrentlyUpdated);
int append(QV4::Object *object);
void insert(int elementIndex, QV4::Object *object);
diff --git a/src/qmlmodels/qqmllistmodelworkeragent_p.h b/src/qmlmodels/qqmllistmodelworkeragent_p.h
index 1ef27cea3f..f65909dcec 100644
--- a/src/qmlmodels/qqmllistmodelworkeragent_p.h
+++ b/src/qmlmodels/qqmllistmodelworkeragent_p.h
@@ -56,6 +56,7 @@
#include <QEvent>
#include <QMutex>
#include <QWaitCondition>
+#include <QtQml/qqml.h>
#include <private/qv4engine_p.h>
@@ -71,6 +72,7 @@ class QQmlListModelWorkerAgent : public QObject
Q_OBJECT
Q_PROPERTY(int count READ count)
Q_PROPERTY(QV4::ExecutionEngine *engine READ engine WRITE setEngine NOTIFY engineChanged)
+ QML_ANONYMOUS
public:
QQmlListModelWorkerAgent(QQmlListModel *);
diff --git a/src/qmlmodels/qqmlmodelsmodule.cpp b/src/qmlmodels/qqmlmodelsmodule.cpp
index 4b753fe49a..7ed8561558 100644
--- a/src/qmlmodels/qqmlmodelsmodule.cpp
+++ b/src/qmlmodels/qqmlmodelsmodule.cpp
@@ -40,16 +40,15 @@
#include "qqmlmodelsmodule_p.h"
#include <private/qtqmlmodelsglobal_p.h>
-#if QT_CONFIG(itemmodel)
-#include <QtCore/qitemselectionmodel.h>
-#endif
#if QT_CONFIG(qml_list_model)
#include <private/qqmllistmodel_p.h>
+#include <private/qqmllistmodelworkeragent_p.h>
#endif
#if QT_CONFIG(qml_delegate_model)
#include <private/qqmldelegatemodel_p.h>
#include <private/qqmldelegatecomponent_p.h>
#include <private/qquickpackage_p.h>
+#include <private/qqmlcomponentattached_p.h>
#endif
#if QT_CONFIG(qml_object_model)
#include <private/qqmlobjectmodel_p.h>
@@ -67,24 +66,20 @@ void QQmlModelsModule::defineModule()
const char uri[] = "QtQml.Models";
#if QT_CONFIG(qml_list_model)
- qmlRegisterType<QQmlListElement>(uri, 2, 0, "ListElement");
- qmlRegisterCustomType<QQmlListModel>(uri, 2, 0, "ListModel", new QQmlListModelParser);
+ qmlRegisterTypesAndRevisions<QQmlListElement, QQmlListModel, QQmlListModelWorkerAgent>(uri, 2);
#endif
#if QT_CONFIG(qml_delegate_model)
+ // TODO: Get rid of these. It's called DelegateModel and DelegateModelGroup these days.
qmlRegisterType<QQmlDelegateModel>(uri, 2, 0, "VisualDataModel");
qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 0, "VisualDataGroup");
- qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
- qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
- qmlRegisterType<QQuickPackage>(uri, 2, 0, "Package");
+
+ qmlRegisterTypesAndRevisions<QQmlDelegateModel, QQmlDelegateModelGroup, QQuickPackage>(uri, 2);
#endif
#if QT_CONFIG(qml_object_model)
- qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
- qmlRegisterType<QQmlObjectModel,3>(uri, 2, 3, "ObjectModel");
- qmlRegisterType<QQmlInstantiator>(uri, 2, 1, "Instantiator");
- qmlRegisterAnonymousType<QQmlInstanceModel>(uri, 2);
+ qmlRegisterTypesAndRevisions<QQmlObjectModel, QQmlInstantiator, QQmlInstanceModel>(uri, 2);
#endif
#if QT_CONFIG(itemmodel)
- qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
+ qmlRegisterTypesAndRevisions<QItemSelectionModelForeign>(uri, 2);
#endif
}
@@ -93,13 +88,11 @@ void QQmlModelsModule::defineLabsModule()
const char uri[] = "Qt.labs.qmlmodels";
#if QT_CONFIG(qml_delegate_model)
- qmlRegisterUncreatableType<QQmlAbstractDelegateComponent>(uri, 1, 0, "AbstractDelegateComponent", QQmlAbstractDelegateComponent::tr("Cannot create instance of abstract class AbstractDelegateComponent."));
- qmlRegisterType<QQmlDelegateChooser>(uri, 1, 0, "DelegateChooser");
- qmlRegisterType<QQmlDelegateChoice>(uri, 1, 0, "DelegateChoice");
+ qmlRegisterTypesAndRevisions<
+ QQmlAbstractDelegateComponent, QQmlDelegateChooser, QQmlDelegateChoice>(uri, 1);
#endif
#if QT_CONFIG(qml_table_model)
- qmlRegisterType<QQmlTableModel>(uri, 1, 0, "TableModel");
- qmlRegisterType<QQmlTableModelColumn>(uri, 1, 0, "TableModelColumn");
+ qmlRegisterTypesAndRevisions<QQmlTableModel, QQmlTableModelColumn>(uri, 1);
#endif
}
diff --git a/src/qmlmodels/qqmlmodelsmodule_p.h b/src/qmlmodels/qqmlmodelsmodule_p.h
index f63052b682..c697b08bf7 100644
--- a/src/qmlmodels/qqmlmodelsmodule_p.h
+++ b/src/qmlmodels/qqmlmodelsmodule_p.h
@@ -51,6 +51,12 @@
// We mean it.
//
+#include <QtQml/qqml.h>
+
+#if QT_CONFIG(itemmodel)
+#include <QtCore/qitemselectionmodel.h>
+#endif
+
#include <private/qtqmlmodelsglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -62,6 +68,16 @@ public:
static void defineLabsModule();
};
+#if QT_CONFIG(itemmodel)
+struct QItemSelectionModelForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QItemSelectionModel)
+ QML_NAMED_ELEMENT(ItemSelectionModel)
+ QML_ADDED_IN_MINOR_VERSION(2)
+};
+#endif
+
QT_END_NAMESPACE
#endif
diff --git a/src/qmlmodels/qqmlobjectmodel.cpp b/src/qmlmodels/qqmlobjectmodel.cpp
index b6330b4295..7409178616 100644
--- a/src/qmlmodels/qqmlobjectmodel.cpp
+++ b/src/qmlmodels/qqmlobjectmodel.cpp
@@ -328,7 +328,7 @@ QObject *QQmlObjectModel::get(int index) const
\qmlmethod QtQml.Models::ObjectModel::append(object item)
\since 5.6
- Appends a new item to the end of the model.
+ Appends a new \a item to the end of the model.
\code
objectModel.append(objectComponent.createObject())
@@ -346,7 +346,7 @@ void QQmlObjectModel::append(QObject *object)
\qmlmethod QtQml.Models::ObjectModel::insert(int index, object item)
\since 5.6
- Inserts a new item to the model at position \a index.
+ Inserts a new \a item to the model at position \a index.
\code
objectModel.insert(2, objectComponent.createObject())
@@ -371,7 +371,7 @@ void QQmlObjectModel::insert(int index, QObject *object)
\qmlmethod QtQml.Models::ObjectModel::move(int from, int to, int n = 1)
\since 5.6
- Moves \a n items \a from one position \a to another.
+ Moves \e n items \a from one position \a to another.
The from and to ranges must exist; for example, to move the first 3 items
to the end of the model:
@@ -398,7 +398,7 @@ void QQmlObjectModel::move(int from, int to, int n)
\qmlmethod QtQml.Models::ObjectModel::remove(int index, int n = 1)
\since 5.6
- Removes the items at \a index from the model.
+ Removes \e n items at \a index from the model.
\sa clear()
*/
diff --git a/src/qmlmodels/qqmlobjectmodel_p.h b/src/qmlmodels/qqmlobjectmodel_p.h
index 78a5615ae2..0aa818d724 100644
--- a/src/qmlmodels/qqmlobjectmodel_p.h
+++ b/src/qmlmodels/qqmlobjectmodel_p.h
@@ -69,6 +69,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlInstanceModel : public QObject
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
+ QML_ANONYMOUS
public:
virtual ~QQmlInstanceModel() {}
@@ -113,6 +114,9 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlObjectModel : public QQmlInstanceModel
Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged DESIGNABLE false)
Q_CLASSINFO("DefaultProperty", "children")
+ QML_NAMED_ELEMENT(ObjectModel)
+ QML_ADDED_IN_MINOR_VERSION(1)
+ QML_ATTACHED(QQmlObjectModelAttached)
public:
QQmlObjectModel(QObject *parent=nullptr);
@@ -191,6 +195,5 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQmlInstanceModel)
QML_DECLARE_TYPE(QQmlObjectModel)
-QML_DECLARE_TYPEINFO(QQmlObjectModel, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQMLINSTANCEMODEL_P_H
diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp
index b244a007e5..9b79df3441 100644
--- a/src/qmlmodels/qqmltableinstancemodel.cpp
+++ b/src/qmlmodels/qqmltableinstancemodel.cpp
@@ -525,8 +525,13 @@ const QAbstractItemModel *QQmlTableInstanceModel::abstractItemModel() const
void QQmlTableInstanceModelIncubationTask::setInitialState(QObject *object)
{
- modelItemToIncubate->object = object;
- emit tableInstanceModel->initItem(modelItemToIncubate->index, object);
+ initializeRequiredProperties(modelItemToIncubate, object);
+ if (QQmlIncubatorPrivate::get(this)->requiredProperties().empty()) {
+ modelItemToIncubate->object = object;
+ emit tableInstanceModel->initItem(modelItemToIncubate->index, object);
+ } else {
+ object->deleteLater();
+ }
}
void QQmlTableInstanceModelIncubationTask::statusChanged(QQmlIncubator::Status status)
diff --git a/src/qmlmodels/qqmltablemodel.cpp b/src/qmlmodels/qqmltablemodel.cpp
index 4a96e7a46b..f190ad86b1 100644
--- a/src/qmlmodels/qqmltablemodel.cpp
+++ b/src/qmlmodels/qqmltablemodel.cpp
@@ -64,7 +64,7 @@ Q_LOGGING_CATEGORY(lcTableModel, "qt.qml.tablemodel")
The model's initial row data is set with either the \l rows property or by
calling \l appendRow(). Each column in the model is specified by declaring
a \l TableModelColumn instance, where the order of each instance determines
- its column index. Once the model's \l Component.completed() signal has been
+ its column index. Once the model's \l Component::completed() signal has been
emitted, the columns and roles will have been established and are then
fixed for the lifetime of the model.
diff --git a/src/qmlmodels/qqmltablemodel_p.h b/src/qmlmodels/qqmltablemodel_p.h
index b3c0cc2848..4b667e1073 100644
--- a/src/qmlmodels/qqmltablemodel_p.h
+++ b/src/qmlmodels/qqmltablemodel_p.h
@@ -72,6 +72,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlTableModel : public QAbstractTableModel, pu
Q_PROPERTY(QQmlListProperty<QQmlTableModelColumn> columns READ columns CONSTANT FINAL)
Q_INTERFACES(QQmlParserStatus)
Q_CLASSINFO("DefaultProperty", "columns")
+ QML_NAMED_ELEMENT(TableModel)
public:
QQmlTableModel(QObject *parent = nullptr);
diff --git a/src/qmlmodels/qqmltablemodelcolumn_p.h b/src/qmlmodels/qqmltablemodelcolumn_p.h
index 0b6478ce38..33f32ccb68 100644
--- a/src/qmlmodels/qqmltablemodelcolumn_p.h
+++ b/src/qmlmodels/qqmltablemodelcolumn_p.h
@@ -96,6 +96,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlTableModelColumn : public QObject
Q_PROPERTY(QJSValue sizeHint READ sizeHint WRITE setSizeHint NOTIFY sizeHintChanged FINAL)
Q_PROPERTY(QJSValue setSizeHint READ getSetSizeHint WRITE setSetSizeHint NOTIFY setSizeHintChanged FINAL)
+ QML_NAMED_ELEMENT(TableModelColumn)
public:
QQmlTableModelColumn(QObject *parent = nullptr);
diff --git a/src/qmlmodels/qquickpackage.cpp b/src/qmlmodels/qquickpackage.cpp
index 03539d8737..567381e5ab 100644
--- a/src/qmlmodels/qquickpackage.cpp
+++ b/src/qmlmodels/qquickpackage.cpp
@@ -47,8 +47,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmltype Package
\instantiates QQuickPackage
- \inqmlmodule QtQuick
- \ingroup qtquick-views
+ \inqmlmodule QtQml.Models
+ \ingroup qtquick-models
\brief Specifies a collection of named items.
The Package type is used in conjunction with
@@ -71,6 +71,9 @@ QT_BEGIN_NAMESPACE
\snippet package/view.qml 0
+ \note Package is part of QtQml.Models since version 2.14 and part of QtQuick since version 2.0.
+ Importing Package via QtQuick is deprecated since Qt 5.14.
+
\sa {Qt Quick Examples - Views}, {Qt Quick Demo - Photo Viewer}, {Qt QML}
*/
diff --git a/src/qmlmodels/qquickpackage_p.h b/src/qmlmodels/qquickpackage_p.h
index 97f7818fee..801b8d8409 100644
--- a/src/qmlmodels/qquickpackage_p.h
+++ b/src/qmlmodels/qquickpackage_p.h
@@ -66,6 +66,8 @@ class Q_AUTOTEST_EXPORT QQuickPackage : public QObject
Q_DECLARE_PRIVATE(QQuickPackage)
Q_CLASSINFO("DefaultProperty", "data")
+ QML_NAMED_ELEMENT(Package)
+ QML_ATTACHED(QQuickPackageAttached)
Q_PROPERTY(QQmlListProperty<QObject> data READ data)
public:
@@ -99,6 +101,5 @@ private:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickPackage)
-QML_DECLARE_TYPEINFO(QQuickPackage, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKPACKAGE_H
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 0bf05093be..d6e4669769 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -18,12 +18,15 @@ qtHaveModule(widgets) {
SOURCES += \
$$PWD/quicktest.cpp \
$$PWD/quicktestevent.cpp \
- $$PWD/quicktestresult.cpp
+ $$PWD/quicktestresult.cpp \
+ $$PWD/quicktestutil.cpp
+
HEADERS += \
$$PWD/quicktestglobal.h \
$$PWD/quicktest.h \
$$PWD/quicktestevent_p.h \
$$PWD/quicktestresult_p.h \
+ $$PWD/quicktestutil_p.h \
$$PWD/qtestoptions_p.h
qtConfig(qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
diff --git a/src/qmltest/quicktestevent_p.h b/src/qmltest/quicktestevent_p.h
index 5208c03a82..a3c2e78e58 100644
--- a/src/qmltest/quicktestevent_p.h
+++ b/src/qmltest/quicktestevent_p.h
@@ -54,6 +54,7 @@
#include <QtQuickTest/quicktestglobal.h>
#include <QtCore/qobject.h>
#include <QtGui/QWindow>
+#include <QtQml/qqml.h>
#include <QtTest/qtesttouch.h>
QT_BEGIN_NAMESPACE
@@ -62,6 +63,8 @@ class QuickTestEvent;
class Q_QUICK_TEST_EXPORT QQuickTouchEventSequence : public QObject
{
Q_OBJECT
+ QML_ANONYMOUS
+
public:
explicit QQuickTouchEventSequence(QuickTestEvent *testEvent, QObject *item = nullptr);
public slots:
@@ -80,6 +83,7 @@ class Q_QUICK_TEST_EXPORT QuickTestEvent : public QObject
{
Q_OBJECT
Q_PROPERTY(int defaultMouseDelay READ defaultMouseDelay FINAL)
+ QML_NAMED_ELEMENT(TestEvent)
public:
QuickTestEvent(QObject *parent = nullptr);
~QuickTestEvent() override;
diff --git a/src/qmltest/quicktestresult_p.h b/src/qmltest/quicktestresult_p.h
index 0d229ad713..296e8e5344 100644
--- a/src/qmltest/quicktestresult_p.h
+++ b/src/qmltest/quicktestresult_p.h
@@ -76,6 +76,8 @@ class Q_QUICK_TEST_EXPORT QuickTestResult : public QObject
Q_PROPERTY(int skipCount READ skipCount)
Q_PROPERTY(QStringList functionsToRun READ functionsToRun)
Q_PROPERTY(QStringList tagsToRun READ tagsToRun)
+ QML_NAMED_ELEMENT(TestResult)
+
public:
QuickTestResult(QObject *parent = nullptr);
~QuickTestResult() override;
diff --git a/src/qmltest/quicktestutil.cpp b/src/qmltest/quicktestutil.cpp
new file mode 100644
index 0000000000..d9e6a2fba5
--- /dev/null
+++ b/src/qmltest/quicktestutil.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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: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 "quicktestutil_p.h"
+
+#include <QtQuickTest/private/qtestoptions_p.h>
+#include <QtQml/private/qqmltype_p.h>
+#include <QtQml/private/qqmlmetatype_p.h>
+#include <QtQml/private/qv4engine_p.h>
+#include <QtQml/private/qv4scopedvalue_p.h>
+
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qstylehints.h>
+#include <QtQml/qqmlengine.h>
+
+QT_BEGIN_NAMESPACE
+
+bool QuickTestUtil::printAvailableFunctions() const
+{
+ return QTest::printAvailableFunctions;
+}
+
+int QuickTestUtil::dragThreshold() const
+{
+ return QGuiApplication::styleHints()->startDragDistance();
+}
+
+QJSValue QuickTestUtil::typeName(const QVariant &v) const
+{
+ QString name = QString::fromUtf8(v.typeName());
+ if (v.canConvert<QObject*>()) {
+ QQmlType type;
+ const QMetaObject *mo = v.value<QObject*>()->metaObject();
+ while (!type.isValid() && mo) {
+ type = QQmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ if (type.isValid()) {
+ name = type.qmlTypeName();
+ }
+ }
+
+ QQmlEngine *engine = qmlEngine(this);
+ QV4::ExecutionEngine *v4 = engine->handle();
+ return QJSValue(v4, v4->newString(name)->asReturnedValue());
+}
+
+bool QuickTestUtil::compare(const QVariant &act, const QVariant &exp) const {
+ return act == exp;
+}
+
+QJSValue QuickTestUtil::callerFile(int frameIndex) const
+{
+ QQmlEngine *engine = qmlEngine(this);
+ QV4::ExecutionEngine *v4 = engine->handle();
+ QV4::Scope scope(v4);
+
+ QVector<QV4::StackFrame> stack = v4->stackTrace(frameIndex + 2);
+ return (stack.size() > frameIndex + 1)
+ ? QJSValue(v4, v4->newString(stack.at(frameIndex + 1).source)->asReturnedValue())
+ : QJSValue();
+}
+
+int QuickTestUtil::callerLine(int frameIndex) const
+{
+ QQmlEngine *engine = qmlEngine(this);
+ QV4::ExecutionEngine *v4 = engine->handle();
+
+ QVector<QV4::StackFrame> stack = v4->stackTrace(frameIndex + 2);
+ if (stack.size() > frameIndex + 1)
+ return stack.at(frameIndex + 1).line;
+ return -1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmltest/quicktestutil_p.h b/src/qmltest/quicktestutil_p.h
new file mode 100644
index 0000000000..74d315df7d
--- /dev/null
+++ b/src/qmltest/quicktestutil_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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: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 QUICKTESTUTIL_P_H
+#define QUICKTESTUTIL_P_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 <QtQuickTest/quicktestglobal.h>
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+#include <QtQml/qjsvalue.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_TEST_EXPORT QuickTestUtil : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool printAvailableFunctions READ printAvailableFunctions NOTIFY printAvailableFunctionsChanged)
+ Q_PROPERTY(int dragThreshold READ dragThreshold NOTIFY dragThresholdChanged)
+ QML_NAMED_ELEMENT(TestUtil)
+public:
+ QuickTestUtil(QObject *parent = nullptr) :QObject(parent) {}
+ ~QuickTestUtil() override {}
+
+ bool printAvailableFunctions() const;
+ int dragThreshold() const;
+
+Q_SIGNALS:
+ void printAvailableFunctionsChanged();
+ void dragThresholdChanged();
+
+public Q_SLOTS:
+
+ QJSValue typeName(const QVariant& v) const;
+ bool compare(const QVariant& act, const QVariant& exp) const;
+
+ QJSValue callerFile(int frameIndex = 0) const;
+ int callerLine(int frameIndex = 0) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QUICKTESTUTIL_P_H
diff --git a/src/qmlworkerscript/doc/qtqmlworkerscript.qdocconf b/src/qmlworkerscript/doc/qtqmlworkerscript.qdocconf
new file mode 100644
index 0000000000..bb883cf39f
--- /dev/null
+++ b/src/qmlworkerscript/doc/qtqmlworkerscript.qdocconf
@@ -0,0 +1,37 @@
+include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+include($QT_INSTALL_DOCS/config/exampleurl-qtdeclarative.qdocconf)
+
+project = QtQmlWorkerScript
+description = Qt Qml WorkerScript Reference Documentation
+version = $QT_VERSION
+moduleheader = QtQmlWorkerScript
+qhp.projects = QtQmlWorkerScript
+
+qhp.QtQmlWorkerScript.file = qtqmlworkerscript.qhp
+qhp.QtQmlWorkerScript.namespace = org.qt-project.qtqmlworkerscript.$QT_VERSION_TAG
+qhp.QtQmlWorkerScript.virtualFolder = qtqmlworkerscript
+qhp.QtQmlWorkerScript.indexRoot =
+
+qhp.QtQmlWorkerScript.filterAttributes = qtqmlworkerscript $QT_VERSION qtrefdoc
+qhp.QtQmlWorkerScript.customFilters.Qt.name = QtQmlWorkerScript $QT_VERSION
+qhp.QtQmlWorkerScript.customFilters.Qt.filterAttributes = qtqmlworkerscript $QT_VERSION
+
+qhp.QtQmlWorkerScript.title = QML Types
+qhp.QtQmlWorkerScript.indexTitle = Qt QML WorkerScript QML Types
+qhp.QtQmlWorkerScript.selectors = qmlclass
+qhp.QtQmlWorkerScript.sortPages = true
+
+tagfile = qtqmlworkerscript.tags
+
+depends += qtcore qtqml qtdoc
+
+headerdirs += ..
+
+sourcedirs += .. \
+ ../../imports/workerscript
+
+exampledirs += ../../../examples/qml \
+ ../ \
+ snippets
+
+navigation.qmltypespage = "Qt Qml WorkerScript QML Types"
diff --git a/src/qmlworkerscript/qmlworkerscript.pro b/src/qmlworkerscript/qmlworkerscript.pro
index 908caa4ed4..9f5e0e809a 100644
--- a/src/qmlworkerscript/qmlworkerscript.pro
+++ b/src/qmlworkerscript/qmlworkerscript.pro
@@ -1,6 +1,8 @@
TARGET = QtQmlWorkerScript
QT = core-private qml-private
+QMAKE_DOCS = $$PWD/doc/qtqmlworkerscript.qdocconf
+
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FOREACH
HEADERS += \
diff --git a/src/qmlworkerscript/qqmlworkerscriptmodule.cpp b/src/qmlworkerscript/qqmlworkerscriptmodule.cpp
index 5eb7d306bc..b85456a633 100644
--- a/src/qmlworkerscript/qqmlworkerscriptmodule.cpp
+++ b/src/qmlworkerscript/qqmlworkerscriptmodule.cpp
@@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
void QQmlWorkerScriptModule::defineModule()
{
const char uri[] = "QtQml.WorkerScript";
- qmlRegisterType<QQuickWorkerScript>(uri, 2, 0, "WorkerScript");
+ qmlRegisterTypesAndRevisions<QQuickWorkerScript>(uri, 2);
}
QT_END_NAMESPACE
diff --git a/src/qmlworkerscript/qquickworkerscript.cpp b/src/qmlworkerscript/qquickworkerscript.cpp
index 4da1def5f5..8b236697b9 100644
--- a/src/qmlworkerscript/qquickworkerscript.cpp
+++ b/src/qmlworkerscript/qquickworkerscript.cpp
@@ -374,7 +374,7 @@ QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine()
yieldCurrentThread();
}
- d->deleteLater();
+ delete d;
}
WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent)
@@ -441,7 +441,7 @@ void QQuickWorkerScriptEngine::run()
\qmltype WorkerScript
\instantiates QQuickWorkerScript
\ingroup qtquick-threading
- \inqmlmodule QtQml
+ \inqmlmodule QtQml.WorkerScript
\brief Enables the use of threads in a Qt Quick application.
Use WorkerScript to run operations in a new thread.
diff --git a/src/qmlworkerscript/qquickworkerscript_p.h b/src/qmlworkerscript/qquickworkerscript_p.h
index 87cf2e9754..9b5d3587fb 100644
--- a/src/qmlworkerscript/qquickworkerscript_p.h
+++ b/src/qmlworkerscript/qquickworkerscript_p.h
@@ -87,6 +87,7 @@ class Q_AUTOTEST_EXPORT QQuickWorkerScript : public QObject, public QQmlParserSt
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ QML_NAMED_ELEMENT(WorkerScript);
Q_INTERFACES(QQmlParserStatus)
public:
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index 13746b13de..91458527dd 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -38,12 +38,14 @@ qhp.QtQuick.subprojects.examples.selectors = fake:example
tagfile = ../../../doc/qtquick/qtquick.tags
-depends += qtcore qtqml qtqmltest qtgui qtlinguist qtquickcontrols1 qtquickcontrols qtdoc qtquickdialogs qtsensors qtwidgets qmake qtmultimedia qtgraphicaleffects qtsql qtxmlpatterns
+depends += qtcore qtqml qtqmltest qtgui qtlinguist qtquickcontrols qtquickcontrols1 qtdoc qtquickdialogs qtsensors qtwidgets qmake qtmultimedia qtgraphicaleffects qtsql qtxmlpatterns
headerdirs += ..\
+ ../../quick \
../../quickwidgets
sourcedirs += .. \
+ ../../quick \
../../quickwidgets
exampledirs += ../../../examples/quick \
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index e4d837112f..7695bb57db 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -227,7 +227,7 @@ access to the data from QML:
The QSqlQueryModel class is good enough to implement a custom read-only
model that represents data in an SQL database. The
-\l{Qt Quick Controls 2 - Chat Tutorial}{chat tutorial} example
+\l{Qt Quick Controls - Chat Tutorial}{chat tutorial} example
demonstrates this very well by implementing a custom model to fetch the
contact details from an SQLite database.
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index b96d09996d..e09c430e43 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -341,9 +341,15 @@ OpenGL application is allowed to draw.
The \l {Scene Graph - OpenGL Under QML} example gives an example on
how to use these signals using OpenGL.
+The \l {Scene Graph - Direct3D 11 Under QML} example gives an example on
+how to use these signals using Direct3D.
+
The \l {Scene Graph - Metal Under QML} example gives an example on
how to use these signals using Metal.
+The \l {Scene Graph - Vulkan Under QML} example gives an example on
+how to use these signals using Vulkan.
+
The other alternative, only available for OpenGL currently, is to create a
QQuickFramebufferObject, render into it, and let it be displayed in the scene
graph as a texture. The \l {Scene Graph - Rendering FBOs} example shows how
@@ -352,6 +358,13 @@ and multiple threads to create content to be displayed in the scene graph. The
\l {Scene Graph - Rendering FBOs in a thread} examples show how this can be
done.
+Graphics APIs other than OpenGL can also follow this approach, even though
+QQuickFramebufferObject does not currently support them. Creating and rendering
+to a texture directly with the underlying API, followed by wrapping and using
+this resource in a Qt Quick scene in a custom QQuickItem, is demonstrated in
+the \l {Scene Graph - Metal Texture Import} example. That example uses Metal,
+the concepts however apply to all other graphics APIs as well.
+
\warning When mixing OpenGL content with scene graph rendering, it is
important the application does not leave the OpenGL context in a state
with buffers bound, attributes enabled, special values in the z-buffer
@@ -1003,6 +1016,14 @@ with multiple windows.
\li Where applicable (Vulkan, Direct3D), enables the graphics API implementation's debug
and/or validation layers, if available.
+ \row
+ \li \c QSG_RHI_PREFER_SOFTWARE_RENDERER
+ \li \c 1
+ \li Requests choosing an adapter or physical device that uses software-based
+ rasterization. Applicable only when the underlying API has support for
+ enumerating adapters (for example, Direct3D or Vulkan), and is ignored
+ otherwise.
+
\endtable
Applications wishing to always run with a single given graphics API, can
@@ -1018,4 +1039,9 @@ with multiple windows.
equivalent in effect to running with both \c QSG_RHI and \c QSG_RHI_BACKEND
set.
+ All QRhi backends will choose the system default GPU adapter or physical
+ device, unless overridden by \c{QSG_RHI_PREFER_SOFTWARE_RENDERER} or a
+ backend-specific variable, such as, \c{QT_D3D_ADAPTER_INDEX} or
+ \c{QT_VK_PHYSICAL_DEVICE_INDEX}. No further adapter configurability is
+ provided at this time.
*/
diff --git a/src/quick/doc/src/examples.qdoc b/src/quick/doc/src/examples.qdoc
index 9034c90eb8..8c31e13a2d 100644
--- a/src/quick/doc/src/examples.qdoc
+++ b/src/quick/doc/src/examples.qdoc
@@ -171,16 +171,17 @@ Creator.
\div {class="doc-column"}
\b{Scene Graph}
\list
- \li \l{Scene Graph - OpenGL Under QML}{OpenGL Under QML}
+ \li \l{Scene Graph - Custom Geometry}{Custom Geometry}
\li \l{Scene Graph - Metal Under QML}{Metal Under QML}
+ \li \l{Scene Graph - Metal Texture Import}{Metal Texture Import}
+ \li \l{Scene Graph - OpenGL Under QML}{OpenGL Under QML}
\li \l{Scene Graph - Direct3D 11 Under QML}{Direct3D 11 Under QML}
+ \li \l{Scene Graph - Custom Rendering with QSGRenderNode}{Render Node}
\li \l{Scene Graph - Painted Item}{Painted Item}
- \li \l{Scene Graph - Custom Geometry}{Custom Geometry}
\li \l{Scene Graph - Graph}{Graph}
\li \l{Scene Graph - Simple Material}{Simple Material}
\li \l{Scene Graph - Rendering FBOs}{Rendering FBOs}
\li \l{Scene Graph - Rendering FBOs in a thread}{Rendering FBOs in a thread}
- \li \l{Scene Graph - Custom Rendering with QSGRenderNode}{Render Node}
\endlist
\enddiv
\enddiv
diff --git a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
index dd7f21e81a..f4a1616943 100644
--- a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
+++ b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
@@ -45,9 +45,9 @@ UI. It is recommended to browse this list of UI controls before creating your
own custom UI control.
Besides these basic UI controls offered by Qt Quick itself, a rich set of UI
-controls are also available with Qt Quick Controls 2. They cater to the most
+controls are also available with Qt Quick Controls. They cater to the most
common use cases without any change, and offer a lot more possibilities with their
-customization options. In particular, Qt Quick Controls 2 provides styling
+customization options. In particular, Qt Quick Controls provides styling
options that align with the latest UI design trends. If these UI controls do not
satisfy your application's needs, only then it is recommended to create a
custom control.
@@ -55,7 +55,7 @@ custom control.
\section2 Related Information
\list
-\li \l{Qt Quick Controls 2}
+\li \l{Qt Quick Controls}
\li \l{Qt Quick}
\endlist
@@ -323,7 +323,7 @@ see \l {Choosing the Correct Integration Method Between C++ and QML}.
\section2 Related Information
\list
\li \l{Integrating QML and C++}
-\li \l{Qt Quick Controls 2 - Chat Tutorial}{Chat application tutorial}
+\li \l{Qt Quick Controls - Chat Tutorial}{Chat application tutorial}
\endlist
\section1 Using Qt Quick Layouts
@@ -426,7 +426,7 @@ developers to follow these tips:
\li Use anchors or the Qt Quick Layouts module to lay out the visual items.
\li Do not specify explicit width and height for a visual item.
\li Provide UI resources such as images and icons for each display resolution
- that your application supports. The Qt Quick Controls 2 gallery example
+ that your application supports. The Qt Quick Controls gallery example
demonstrates this well by providing the \c qt-logo.png for \c @2x, \c @3x,
and \c @4x resolutions, enabling the application to cater to high
resolution displays. Qt automatically chooses the appropriate
@@ -437,7 +437,7 @@ developers to follow these tips:
versions of an image, as is necessary with bitmap images.
\li Use font-based icons, such as Font Awesome. These scale to any display
resolution, and also allow colorization. The
- Qt Quick Controls 2 Text Editor example demonstrates this well.
+ Qt Quick Controls Text Editor example demonstrates this well.
\endlist
With this in place, your application's UI should scale depending
@@ -448,8 +448,8 @@ on the display resolution on offer.
\section2 Related Information
\list
- \li \l{Qt Quick Controls 2 - Gallery}{Gallery example}
- \li \l{Qt Quick Controls 2 - Text Editor}{Text Editor example}
+ \li \l{Qt Quick Controls - Gallery}{Gallery example}
+ \li \l{Qt Quick Controls - Text Editor}{Text Editor example}
\li \l{Font Awesome}
\li \l{Scalability}
\li \l{High DPI Displays}
diff --git a/src/quick/doc/src/guidelines/qtquick-toolsnutilities.qdoc b/src/quick/doc/src/guidelines/qtquick-toolsnutilities.qdoc
index 0669ec06c8..84741efa61 100644
--- a/src/quick/doc/src/guidelines/qtquick-toolsnutilities.qdoc
+++ b/src/quick/doc/src/guidelines/qtquick-toolsnutilities.qdoc
@@ -39,15 +39,15 @@ information about them.
The Qt Quick Designer enables designing Qt Quick-based UIs using simple
drag-n-drop gestures that most designers are familiar with. It offers UI
-elements from the Qt Quick and Qt Quick Controls 2 modules, as well as
+elements from the Qt Quick and Qt Quick Controls modules, as well as
integration for custom UI elements.
The following is a list of example applications that use UIs created by
the Qt Quick Designer:
\list
- \li \l{Qt Quick Controls 2 - Contact List}
- \li \l{Qt Quick Controls 2 - Flat Style}
+ \li \l{Qt Quick Controls - Contact List}
+ \li \l{Qt Quick Controls - Flat Style}
\endlist
\section2 QML Debugger and Profiler
diff --git a/src/quick/doc/src/qtquick.qdoc b/src/quick/doc/src/qtquick.qdoc
index 7f72217279..4b843f366b 100644
--- a/src/quick/doc/src/qtquick.qdoc
+++ b/src/quick/doc/src/qtquick.qdoc
@@ -43,7 +43,7 @@ QML types for creating user interfaces with the QML language, and a
\l{Qt Quick C++ Classes}{C++ API} for extending QML applications with C++ code.
\note A set of Qt Quick-based UI controls is also available to create user
-interfaces. See \l{Qt Quick Controls 2} for more information.
+interfaces. See \l{Qt Quick Controls} for more information.
For those new to QML and Qt Quick, please see
\l{QML Applications}
diff --git a/src/quick/handlers/qquickdragaxis_p.h b/src/quick/handlers/qquickdragaxis_p.h
index a4649d5eb9..ef74902122 100644
--- a/src/quick/handlers/qquickdragaxis_p.h
+++ b/src/quick/handlers/qquickdragaxis_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <QtQml/qqml.h>
#include <private/qtquickglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +62,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickDragAxis : public QObject
Q_PROPERTY(qreal minimum READ minimum WRITE setMinimum NOTIFY minimumChanged)
Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ QML_NAMED_ELEMENT(DragAxis)
+ QML_ADDED_IN_MINOR_VERSION(12)
+ QML_UNCREATABLE("DragAxis is only available as a grouped property of DragHandler.")
public:
QQuickDragAxis();
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 61b66beff4..492897b68b 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -39,6 +39,7 @@
#include "qquickdraghandler_p.h"
#include <private/qquickwindow_p.h>
+#include <private/qquickmultipointhandler_p_p.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
@@ -228,7 +229,7 @@ void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
accumulatedDragDelta.setY(0);
}
qreal angle = std::atan2(accumulatedDragDelta.y(), accumulatedDragDelta.x()) * 180 / M_PI;
- bool overThreshold = QQuickWindowPrivate::dragOverThreshold(accumulatedDragDelta);
+ bool overThreshold = d_func()->dragOverThreshold(accumulatedDragDelta);
qCDebug(lcDragHandler) << "movement" << accumulatedDragDelta << "angle" << angle << "of point" << point
<< "pressed @" << point->scenePressPosition() << "over threshold?" << overThreshold;
minAngle = qMin(angle, minAngle);
diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h
index e8f47163ed..22d51c78ec 100644
--- a/src/quick/handlers/qquickdraghandler_p.h
+++ b/src/quick/handlers/qquickdraghandler_p.h
@@ -63,6 +63,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickDragHandler : public QQuickMultiPointHandler
Q_PROPERTY(QQuickDragAxis * yAxis READ yAxis CONSTANT)
Q_PROPERTY(QVector2D translation READ translation NOTIFY translationChanged)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged REVISION 14)
+ QML_NAMED_ELEMENT(DragHandler)
+ QML_ADDED_IN_MINOR_VERSION(12)
public:
enum SnapMode {
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
index d7566f0cd8..79cb288af8 100644
--- a/src/quick/handlers/qquickhoverhandler.cpp
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -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 QtQuick module of the Qt Toolkit.
@@ -47,14 +47,24 @@ Q_LOGGING_CATEGORY(lcHoverHandler, "qt.quick.handler.hover")
/*!
\qmltype HoverHandler
\instantiates QQuickHoverHandler
+ \inherits SinglePointHandler
\inqmlmodule QtQuick
\ingroup qtquick-input-handlers
\brief Handler for mouse and tablet hover.
- HoverHandler detects a hovering cursor. Since touchscreens don't generally
- offer hover events, in practice it detects a hovering mouse or tablet stylus.
+ HoverHandler detects a hovering mouse or tablet stylus cursor.
- \sa MouseArea
+ A binding to the \l hovered property is the easiest way to react when the
+ cursor enters or leaves the \l {PointerHandler::parent}{parent} Item.
+ The \l {SinglePointHandler::point}{point} property provides more detail,
+ including the cursor position. The
+ \l {PointerDeviceHandler::acceptedDevices}{acceptedDevices},
+ \l {PointerDeviceHandler::acceptedPointerTypes}{acceptedPointerTypes},
+ and \l {PointerDeviceHandler::acceptedModifiers}{acceptedModifiers}
+ properties can be used to narrow the behavior to detect hovering of
+ specific kinds of devices or while holding a modifier key.
+
+ \sa MouseArea, PointHandler
*/
QQuickHoverHandler::QQuickHoverHandler(QQuickItem *parent)
@@ -62,9 +72,6 @@ QQuickHoverHandler::QQuickHoverHandler(QQuickItem *parent)
{
// Tell QQuickPointerDeviceHandler::wantsPointerEvent() to ignore button state
d_func()->acceptedButtons = Qt::NoButton;
- // Rule out the touchscreen for now (can be overridden in QML in case a hover-detecting touchscreen exists)
- setAcceptedDevices(static_cast<QQuickPointerDevice::DeviceType>(
- static_cast<int>(QQuickPointerDevice::AllDevices) ^ static_cast<int>(QQuickPointerDevice::TouchScreen)));
}
QQuickHoverHandler::~QQuickHoverHandler()
@@ -93,10 +100,22 @@ bool QQuickHoverHandler::wantsPointerEvent(QQuickPointerEvent *event)
void QQuickHoverHandler::handleEventPoint(QQuickEventPoint *point)
{
- setHovered(true);
+ bool hovered = true;
+ if (point->state() == QQuickEventPoint::Released &&
+ point->pointerEvent()->device()->pointerType() == QQuickPointerDevice::Finger)
+ hovered = false;
+ setHovered(hovered);
setPassiveGrab(point);
}
+/*!
+ \qmlproperty bool QtQuick::HoverHandler::hovered
+ \readonly
+
+ Holds true whenever any pointing device cursor (mouse or tablet) is within
+ the bounds of the \c parent Item, extended by the
+ \l {PointerHandler::margin}{margin}, if any.
+*/
void QQuickHoverHandler::setHovered(bool hovered)
{
if (m_hovered != hovered) {
diff --git a/src/quick/handlers/qquickhoverhandler_p.h b/src/quick/handlers/qquickhoverhandler_p.h
index d8e5fc00a1..e4786bfa53 100644
--- a/src/quick/handlers/qquickhoverhandler_p.h
+++ b/src/quick/handlers/qquickhoverhandler_p.h
@@ -62,6 +62,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickHoverHandler : public QQuickSinglePointHandle
{
Q_OBJECT
Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged)
+ QML_NAMED_ELEMENT(HoverHandler)
+ QML_ADDED_IN_MINOR_VERSION(12)
public:
explicit QQuickHoverHandler(QQuickItem *parent = nullptr);
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index 0afc9997aa..f404788de4 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -364,7 +364,7 @@ void QQuickMultiPointHandler::acceptPoints(const QVector<QQuickEventPoint *> &po
point->setAccepted();
}
-bool QQuickMultiPointHandler::grabPoints(QVector<QQuickEventPoint *> points)
+bool QQuickMultiPointHandler::grabPoints(const QVector<QQuickEventPoint *> &points)
{
if (points.isEmpty())
return false;
diff --git a/src/quick/handlers/qquickmultipointhandler_p.h b/src/quick/handlers/qquickmultipointhandler_p.h
index eeb4b13b83..480f69035b 100644
--- a/src/quick/handlers/qquickmultipointhandler_p.h
+++ b/src/quick/handlers/qquickmultipointhandler_p.h
@@ -107,7 +107,7 @@ protected:
QVector<PointData> angles(const QPointF &ref) const;
static qreal averageAngleDelta(const QVector<PointData> &old, const QVector<PointData> &newAngles);
void acceptPoints(const QVector<QQuickEventPoint *> &points);
- bool grabPoints(QVector<QQuickEventPoint *> points);
+ bool grabPoints(const QVector<QQuickEventPoint *> &points);
void moveTarget(QPointF pos);
Q_DECLARE_PRIVATE(QQuickMultiPointHandler)
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index 9ef0f895ac..5b30d08557 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -43,6 +43,7 @@
#include <private/qsgadaptationlayer_p.h>
#include <private/qquickitem_p.h>
#include <private/qguiapplication_p.h>
+#include <private/qquickmultipointhandler_p_p.h>
#include <private/qquickwindow_p.h>
#include <QEvent>
#include <QMouseEvent>
@@ -338,8 +339,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
const QVector2D currentCentroid(centroid().scenePosition());
const QVector2D pressCentroid(centroid().scenePressPosition());
- QStyleHints *styleHints = QGuiApplication::styleHints();
- const int dragThreshold = styleHints->startDragDistance();
+ const int dragThreshold = QQuickPointerHandler::dragThreshold();
const int dragThresholdSquared = dragThreshold * dragThreshold;
double accumulatedCentroidDistance = 0; // Used to detect scale
@@ -399,7 +399,8 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
point->setAccepted(false); // don't stop propagation
setPassiveGrab(point);
}
- if (QQuickWindowPrivate::dragOverThreshold(point))
+ Q_D(QQuickMultiPointHandler);
+ if (d->dragOverThreshold(point))
++numberOfPointsDraggedOverThreshold;
}
diff --git a/src/quick/handlers/qquickpinchhandler_p.h b/src/quick/handlers/qquickpinchhandler_p.h
index cea794f0c8..708c836acf 100644
--- a/src/quick/handlers/qquickpinchhandler_p.h
+++ b/src/quick/handlers/qquickpinchhandler_p.h
@@ -78,6 +78,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPinchHandler : public QQuickMultiPointHandler
#endif
Q_PROPERTY(QQuickDragAxis * xAxis READ xAxis CONSTANT)
Q_PROPERTY(QQuickDragAxis * yAxis READ yAxis CONSTANT)
+ QML_NAMED_ELEMENT(PinchHandler)
+ QML_ADDED_IN_MINOR_VERSION(12)
public:
explicit QQuickPinchHandler(QQuickItem *parent = nullptr);
diff --git a/src/quick/handlers/qquickpointerdevicehandler.cpp b/src/quick/handlers/qquickpointerdevicehandler.cpp
index 449d726b78..90f31bf9fd 100644
--- a/src/quick/handlers/qquickpointerdevicehandler.cpp
+++ b/src/quick/handlers/qquickpointerdevicehandler.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** 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.
@@ -230,6 +230,55 @@ void QQuickPointerDeviceHandler::setAcceptedPointerTypes(QQuickPointerDevice::Po
}
}
\endqml
+
+ If you set \c acceptedModifiers to an OR combination of modifier keys,
+ it means \e all of those modifiers must be pressed to activate the handler:
+
+ \qml
+ Item {
+ TapHandler {
+ acceptedModifiers: Qt.ControlModifier | Qt.AltModifier | Qt.ShiftModifier
+ onTapped: console.log("control-alt-shift-tapped")
+ }
+ }
+ \endqml
+
+ The available modifiers are as follows:
+
+ \value NoModifier No modifier key is allowed.
+ \value ShiftModifier A Shift key on the keyboard must be pressed.
+ \value ControlModifier A Ctrl key on the keyboard must be pressed.
+ \value AltModifier An Alt key on the keyboard must be pressed.
+ \value MetaModifier A Meta key on the keyboard must be pressed.
+ \value KeypadModifier A keypad button must be pressed.
+ \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument).
+ A Mode_switch key on the keyboard must be pressed.
+ \value KeyboardModifierMask The handler does not care which modifiers are pressed.
+
+ If you need even more complex behavior than can be achieved with
+ combinations of multiple handlers with multiple modifier flags, you can
+ check the modifiers in JavaScript code:
+
+ \qml
+ Item {
+ TapHandler {
+ onTapped:
+ switch (point.modifiers) {
+ case Qt.ControlModifier | Qt.AltModifier:
+ console.log("CTRL+ALT");
+ break;
+ case Qt.ControlModifier | Qt.AltModifier | Qt.MetaModifier:
+ console.log("CTRL+META+ALT");
+ break;
+ default:
+ console.log("other modifiers", point.modifiers);
+ break;
+ }
+ }
+ }
+ \endqml
+
+ \sa Qt::KeyboardModifier
*/
void QQuickPointerDeviceHandler::setAcceptedModifiers(Qt::KeyboardModifiers acceptedModifiers)
{
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index ee0a8e7837..884ebd3b86 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -113,6 +113,47 @@ void QQuickPointerHandler::setMargin(qreal pointDistanceThreshold)
}
/*!
+ \qmlproperty int PointerHandler::dragThreshold
+ \since 5.15
+
+ The distance in pixels that the user must drag an event point in order to
+ have it treated as a drag gesture.
+
+ The default value depends on the platform and screen resolution.
+ It can be reset back to the default value by setting it to undefined.
+ The behavior when a drag gesture begins varies in different handlers.
+*/
+int QQuickPointerHandler::dragThreshold() const
+{
+ Q_D(const QQuickPointerHandler);
+ if (d->dragThreshold < 0)
+ return qApp->styleHints()->startDragDistance();
+ return d->dragThreshold;
+}
+
+void QQuickPointerHandler::setDragThreshold(int t)
+{
+ Q_D(QQuickPointerHandler);
+ if (d->dragThreshold == t)
+ return;
+
+ if (t > std::numeric_limits<qint16>::max())
+ qWarning() << "drag threshold cannot exceed" << std::numeric_limits<qint16>::max();
+ d->dragThreshold = qint16(t);
+ emit dragThresholdChanged();
+}
+
+void QQuickPointerHandler::resetDragThreshold()
+{
+ Q_D(QQuickPointerHandler);
+ if (d->dragThreshold < 0)
+ return;
+
+ d->dragThreshold = -1;
+ emit dragThresholdChanged();
+}
+
+/*!
Notification that the grab has changed in some way which is relevant to this handler.
The \a grabber (subject) will be the Input Handler whose state is changing,
or null if the state change regards an Item.
@@ -547,4 +588,32 @@ QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
{
}
+template <typename TEventPoint>
+bool QQuickPointerHandlerPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint *p) const
+{
+ Q_Q(const QQuickPointerHandler);
+ QStyleHints *styleHints = qApp->styleHints();
+ bool overThreshold = qAbs(d) > q->dragThreshold();
+ const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
+ if (!overThreshold && dragVelocityLimitAvailable) {
+ qreal velocity = qreal(axis == Qt::XAxis ? p->velocity().x() : p->velocity().y());
+ overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
+ }
+ return overThreshold;
+}
+
+bool QQuickPointerHandlerPrivate::dragOverThreshold(QVector2D delta) const
+{
+ Q_Q(const QQuickPointerHandler);
+ const float threshold = q->dragThreshold();
+ return qAbs(delta.x()) > threshold || qAbs(delta.y()) > threshold;
+}
+
+bool QQuickPointerHandlerPrivate::dragOverThreshold(const QQuickEventPoint *point) const
+{
+ QPointF delta = point->scenePosition() - point->scenePressPosition();
+ return (dragOverThreshold(delta.x(), Qt::XAxis, point) ||
+ dragOverThreshold(delta.y(), Qt::YAxis, point));
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickpointerhandler_p.h b/src/quick/handlers/qquickpointerhandler_p.h
index c600e42491..34ae9ce2c2 100644
--- a/src/quick/handlers/qquickpointerhandler_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p.h
@@ -71,6 +71,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandler : public QObject, public QQmlP
Q_PROPERTY(QQuickItem * parent READ parentItem CONSTANT)
Q_PROPERTY(GrabPermissions grabPermissions READ grabPermissions WRITE setGrabPermissions NOTIFY grabPermissionChanged)
Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged)
+ Q_PROPERTY(int dragThreshold READ dragThreshold WRITE setDragThreshold RESET resetDragThreshold NOTIFY dragThresholdChanged REVISION 15)
+
+ QML_NAMED_ELEMENT(PointerHandler)
+ QML_UNCREATABLE("PointerHandler is an abstract base class.")
+ QML_ADDED_IN_MINOR_VERSION(12)
public:
explicit QQuickPointerHandler(QQuickItem *parent = nullptr);
@@ -110,11 +115,16 @@ public:
qreal margin() const;
void setMargin(qreal pointDistanceThreshold);
+ int dragThreshold() const;
+ void setDragThreshold(int t);
+ void resetDragThreshold();
+
Q_SIGNALS:
void enabledChanged();
void activeChanged();
void targetChanged();
void marginChanged();
+ Q_REVISION(15) void dragThresholdChanged();
void grabChanged(QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point);
void grabPermissionChanged();
void canceled(QQuickEventPoint *point);
diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h
index 2ea4905643..5727b1ef55 100644
--- a/src/quick/handlers/qquickpointerhandler_p_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p_p.h
@@ -68,9 +68,16 @@ public:
QQuickPointerHandlerPrivate();
+ template<typename TEventPoint>
+ bool dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint *p) const;
+
+ bool dragOverThreshold(QVector2D delta) const;
+ bool dragOverThreshold(const QQuickEventPoint *point) const;
+
QQuickPointerEvent *currentEvent = nullptr;
QQuickItem *target = nullptr;
qreal m_margin = 0;
+ qint16 dragThreshold = -1; // -1 means use the platform default
uint8_t grabPermissions : 8;
bool enabled : 1;
bool active : 1;
diff --git a/src/quick/handlers/qquickpointhandler_p.h b/src/quick/handlers/qquickpointhandler_p.h
index c197cb4f20..42677540a7 100644
--- a/src/quick/handlers/qquickpointhandler_p.h
+++ b/src/quick/handlers/qquickpointhandler_p.h
@@ -59,6 +59,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointHandler : public QQuickSinglePointHandle
{
Q_OBJECT
Q_PROPERTY(QVector2D translation READ translation NOTIFY translationChanged)
+ QML_NAMED_ELEMENT(PointHandler)
+ QML_ADDED_IN_MINOR_VERSION(12)
public:
explicit QQuickPointHandler(QQuickItem *parent = nullptr);
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index a10064a665..272ebe6b63 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -97,13 +97,6 @@ QQuickTapHandler::QQuickTapHandler(QQuickItem *parent)
}
}
-static bool dragOverThreshold(const QQuickEventPoint *point)
-{
- QPointF delta = point->scenePosition() - point->scenePressPosition();
- return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) ||
- QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point));
-}
-
bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point)
{
if (!point->pointerEvent()->asPointerMouseEvent() &&
@@ -115,7 +108,7 @@ bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point)
// (e.g. DragHandler) gets a chance to take over.
// Don't forget to emit released in case of a cancel.
bool ret = false;
- bool overThreshold = dragOverThreshold(point);
+ bool overThreshold = d_func()->dragOverThreshold(point);
if (overThreshold) {
m_longPressTimer.stop();
m_holdTimer.invalidate();
@@ -386,7 +379,7 @@ void QQuickTapHandler::updateTimeHeld()
That is, if you press and release a touchpoint or button within a time
period less than \l longPressThreshold, while any movement does not exceed
the drag threshold, then the \c tapped signal will be emitted at the time
- of release. The \c eventPoint signal parameter contains information
+ of release. The \a eventPoint signal parameter contains information
from the release event about the point that was tapped:
\snippet pointerHandlers/tapHandlerOnTapped.qml 0
@@ -399,7 +392,7 @@ void QQuickTapHandler::updateTimeHeld()
This signal is emitted when the \c parent Item is tapped once.
After an amount of time greater than QStyleHints::mouseDoubleClickInterval,
it can be tapped again; but if the time until the next tap is less,
- \l tapCount will increase. The \c eventPoint signal parameter contains
+ \l tapCount will increase. The \a eventPoint signal parameter contains
information from the release event about the point that was tapped.
*/
@@ -411,13 +404,13 @@ void QQuickTapHandler::updateTimeHeld()
short span of time (QStyleHints::mouseDoubleClickInterval()) and distance
(QStyleHints::mouseDoubleClickDistance() or
QStyleHints::touchDoubleTapDistance()). This signal always occurs after
- \l singleTapped, \l tapped, and \l tapCountChanged. The \c eventPoint
+ \l singleTapped, \l tapped, and \l tapCountChanged. The \a eventPoint
signal parameter contains information from the release event about the
point that was tapped.
*/
/*!
- \qmlsignal QtQuick::TapHandler::longPressed
+ \qmlsignal QtQuick::TapHandler::longPressed()
This signal is emitted when the \c parent Item is pressed and held for a
time period greater than \l longPressThreshold. That is, if you press and
@@ -427,7 +420,7 @@ void QQuickTapHandler::updateTimeHeld()
*/
/*!
- \qmlsignal QtQuick::TapHandler::tapCountChanged
+ \qmlsignal QtQuick::TapHandler::tapCountChanged()
This signal is emitted when the \c parent Item is tapped once or more (within
a specified time and distance span) and when the present \c tapCount differs
diff --git a/src/quick/handlers/qquicktaphandler_p.h b/src/quick/handlers/qquicktaphandler_p.h
index 56e08590b2..07454bccb8 100644
--- a/src/quick/handlers/qquicktaphandler_p.h
+++ b/src/quick/handlers/qquicktaphandler_p.h
@@ -67,6 +67,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTapHandler : public QQuickSinglePointHandler
Q_PROPERTY(qreal longPressThreshold READ longPressThreshold WRITE setLongPressThreshold NOTIFY longPressThresholdChanged)
Q_PROPERTY(GesturePolicy gesturePolicy READ gesturePolicy WRITE setGesturePolicy NOTIFY gesturePolicyChanged)
+ QML_NAMED_ELEMENT(TapHandler)
+ QML_ADDED_IN_MINOR_VERSION(12)
+
public:
enum GesturePolicy {
DragThreshold,
diff --git a/src/quick/handlers/qquickwheelhandler_p.h b/src/quick/handlers/qquickwheelhandler_p.h
index f8d1c00726..26b052c5b3 100644
--- a/src/quick/handlers/qquickwheelhandler_p.h
+++ b/src/quick/handlers/qquickwheelhandler_p.h
@@ -72,6 +72,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickWheelHandler : public QQuickSinglePointHandle
Q_PROPERTY(qreal targetScaleMultiplier READ targetScaleMultiplier WRITE setTargetScaleMultiplier NOTIFY targetScaleMultiplierChanged)
Q_PROPERTY(bool targetTransformAroundCursor READ isTargetTransformAroundCursor WRITE setTargetTransformAroundCursor NOTIFY targetTransformAroundCursorChanged)
+ QML_NAMED_ELEMENT(WheelHandler)
+ QML_ADDED_IN_MINOR_VERSION(14)
+
public:
explicit QQuickWheelHandler(QQuickItem *parent = nullptr);
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index ac4e86d8da..b8e6d58af4 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -848,13 +848,15 @@ QSGTextureProvider *QQuickCanvasItem::textureProvider() const
The \a contextId parameter names the required context. The Canvas item
will return a context that implements the required drawing mode. After the
first call to getContext, any subsequent call to getContext with the same
- contextId will return the same context object.
+ contextId will return the same context object. Any additional arguments
+ (\a args) are currently ignored.
If the context type is not supported or the canvas has previously been
requested to provide a different and incompatible context type, \c null
will be returned.
Canvas only supports a 2d context.
+
*/
void QQuickCanvasItem::getContext(QQmlV4Function *args)
@@ -897,7 +899,7 @@ void QQuickCanvasItem::getContext(QQmlV4Function *args)
/*!
\qmlmethod int QtQuick::Canvas::requestAnimationFrame(callback)
- This function schedules callback to be invoked before composing the Qt Quick
+ This function schedules \a callback to be invoked before composing the Qt Quick
scene.
*/
@@ -960,7 +962,7 @@ void QQuickCanvasItem::requestPaint()
/*!
\qmlmethod QtQuick::Canvas::markDirty(rect area)
- Mark the given \a area as dirty, so that when this area is visible the
+ Marks the given \a area as dirty, so that when this area is visible the
canvas renderer will redraw it. This will trigger the \c paint signal.
\sa paint, requestPaint()
@@ -984,16 +986,16 @@ void QQuickCanvasItem::checkAnimationCallbacks()
}
/*!
- \qmlmethod bool QtQuick::Canvas::save(string filename)
+ \qmlmethod bool QtQuick::Canvas::save(string filename)
- Save the current canvas content into an image file \a filename.
- The saved image format is automatically decided by the \a filename's
- suffix.
+ Saves the current canvas content into an image file \a filename.
+ The saved image format is automatically decided by the \a filename's
+ suffix. Returns \c true on success.
- Note: calling this method will force painting the whole canvas, not just the
- current canvas visible window.
+ \note Calling this method will force painting the whole canvas, not just the
+ current canvas visible window.
- \sa canvasWindow, canvasSize, toDataURL()
+ \sa canvasWindow, canvasSize, toDataURL()
*/
bool QQuickCanvasItem::save(const QString &filename) const
{
@@ -1023,15 +1025,17 @@ QQmlRefPointer<QQuickCanvasPixmap> QQuickCanvasItem::loadedPixmap(const QUrl& ur
*/
/*!
- \qmlmethod QtQuick::Canvas::loadImage(url image)
- Loads the given \c image asynchronously.
+ \qmlmethod QtQuick::Canvas::loadImage(url image)
+
+ Loads the given \a image asynchronously.
- When the image is ready, \l imageLoaded will be emitted.
- The loaded image can be unloaded by the unloadImage() method.
+ Once the image is ready, imageLoaded() signal will be emitted.
+ The loaded image can be unloaded with the unloadImage() method.
- Note: Only loaded images can be painted on the Canvas item.
- \sa unloadImage, imageLoaded, isImageLoaded(),
- Context2D::createImageData(), Context2D::drawImage()
+ \note Only loaded images can be painted on the Canvas item.
+
+ \sa unloadImage(), imageLoaded(), isImageLoaded(),
+ Context2D::createImageData(), Context2D::drawImage()
*/
void QQuickCanvasItem::loadImage(const QUrl& url)
{
@@ -1051,14 +1055,15 @@ void QQuickCanvasItem::loadImage(const QUrl& url)
}
}
/*!
- \qmlmethod QtQuick::Canvas::unloadImage(url image)
- Unloads the \c image.
+ \qmlmethod QtQuick::Canvas::unloadImage(url image)
+
+ Unloads the \a image.
- Once an image is unloaded it cannot be painted by the canvas context
- unless it is loaded again.
+ Once an image is unloaded, it cannot be painted by the canvas context
+ unless it is loaded again.
- \sa loadImage(), imageLoaded, isImageLoaded(),
- Context2D::createImageData(), Context2D::drawImage
+ \sa loadImage(), imageLoaded(), isImageLoaded(),
+ Context2D::createImageData(), Context2D::drawImage
*/
void QQuickCanvasItem::unloadImage(const QUrl& url)
{
@@ -1067,10 +1072,11 @@ void QQuickCanvasItem::unloadImage(const QUrl& url)
}
/*!
- \qmlmethod QtQuick::Canvas::isImageError(url image)
- Returns true if the \a image failed to load.
+ \qmlmethod QtQuick::Canvas::isImageError(url image)
- \sa loadImage()
+ Returns \c true if the \a image failed to load, \c false otherwise.
+
+ \sa loadImage()
*/
bool QQuickCanvasItem::isImageError(const QUrl& url) const
{
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index cd2977429b..6575caf806 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -99,6 +99,7 @@ class QQuickCanvasItem : public QQuickItem
Q_PROPERTY(QRectF canvasWindow READ canvasWindow WRITE setCanvasWindow NOTIFY canvasWindowChanged)
Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
Q_PROPERTY(RenderStrategy renderStrategy READ renderStrategy WRITE setRenderStrategy NOTIFY renderStrategyChanged)
+ QML_NAMED_ELEMENT(Canvas)
public:
enum RenderTarget {
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 48e5a4d4a2..54cda72a36 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -1148,6 +1148,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(const QV4::FunctionO
/*!
\qmlmethod object QtQuick::Context2D::setTransform(real a, real b, real c, real d, real e, real f)
+
Changes the transformation matrix to the matrix given by the arguments as described below.
Modifying the transformation matrix directly enables you to perform scaling,
@@ -1160,21 +1161,22 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(const QV4::FunctionO
\image qml-item-canvas-math.png
where:
\list
- \li \c{a} is the scale factor in the horizontal (x) direction
+ \li \a{a} is the scale factor in the horizontal (x) direction
\image qml-item-canvas-scalex.png
- \li \c{c} is the skew factor in the x direction
+ \li \a{c} is the skew factor in the x direction
\image qml-item-canvas-skewx.png
- \li \c{e} is the translation in the x direction
+ \li \a{e} is the translation in the x direction
\image qml-item-canvas-translate.png
- \li \c{b} is the skew factor in the y (vertical) direction
+ \li \a{b} is the skew factor in the y (vertical) direction
\image qml-item-canvas-skewy.png
- \li \c{d} is the scale factor in the y direction
+ \li \a{d} is the scale factor in the y direction
\image qml-item-canvas-scaley.png
- \li \c{f} is the translation in the y direction
+ \li \a{f} is the translation in the y direction
\image qml-item-canvas-translatey.png
\li the last row remains constant
\endlist
- The scale factors and skew factors are multiples; \c{e} and \c{f} are
+
+ The scale factors and skew factors are multiples; \a{e} and \a{f} are
coordinate space units, just like the units in the translate(x,y)
method.
@@ -1202,11 +1204,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(const QV4::Fu
/*!
\qmlmethod object QtQuick::Context2D::transform(real a, real b, real c, real d, real e, real f)
- This method is very similar to setTransform(), but instead of replacing the old
- transform matrix, this method applies the given tranform matrix to the current matrix by multiplying to it.
+ This method is very similar to setTransform(), but instead of replacing
+ the old transform matrix, this method applies the given tranform matrix
+ to the current matrix by multiplying to it.
- The setTransform(a, b, c, d, e, f) method actually resets the current transform to the identity matrix,
- and then invokes the transform(a, b, c, d, e, f) method with the same arguments.
+ The setTransform(\a a, \a b, \a c, \a d, \a e, \a f) method actually
+ resets the current transform to the identity matrix, and then invokes
+ the transform(\a a, \a b, \a c, \a d, \a e, \a f) method with the same
+ arguments.
\sa setTransform()
*/
@@ -1626,9 +1631,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(const
}
/*!
- \qmlmethod object QtQuick::Context2D::createRadialGradient(real x0, real y0, real r0, real x1, real y1, real r1)
- Returns a CanvasGradient object that represents a radial gradient that paints along the cone given by the start circle with
- origin (x0, y0) and radius r0, and the end circle with origin (x1, y1) and radius r1.
+ \qmlmethod object QtQuick::Context2D::createRadialGradient(real x0, real y0, real r0, real x1, real y1, real r1)
+
+ Returns a CanvasGradient object that represents a radial gradient that
+ paints along the cone given by the start circle with origin (\a x0, \a y0)
+ and radius \a r0, and the end circle with origin (\a x1, \a y1) and radius
+ \a r1.
\sa CanvasGradient::addColorStop()
\sa createLinearGradient()
@@ -1679,8 +1687,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(const
/*!
\qmlmethod object QtQuick::Context2D::createConicalGradient(real x, real y, real angle)
- Returns a CanvasGradient object that represents a conical gradient that interpolate colors counter-clockwise around a center point (\c x, \c y)
- with start angle \c angle in units of radians.
+
+ Returns a CanvasGradient object that represents a conical gradient that
+ interpolates colors counter-clockwise around a center point (\a x, \a y)
+ with a start angle \a angle in units of radians.
\sa CanvasGradient::addColorStop()
\sa createLinearGradient()
@@ -2263,8 +2273,10 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(const QV4::FunctionObject
//rects
/*!
- \qmlmethod object QtQuick::Context2D::clearRect(real x, real y, real w, real h)
- Clears all pixels on the canvas in the given rectangle to transparent black.
+ \qmlmethod object QtQuick::Context2D::clearRect(real x, real y, real w, real h)
+
+ Clears all pixels on the canvas in the rectangle specified by
+ (\a x, \a y, \a w, \a h) to transparent black.
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2283,8 +2295,9 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(const QV4::Funct
}
/*!
- \qmlmethod object QtQuick::Context2D::fillRect(real x, real y, real w, real h)
- Paint the specified rectangular area using the fillStyle.
+ \qmlmethod object QtQuick::Context2D::fillRect(real x, real y, real w, real h)
+
+ Paints a rectangular area specified by (\a x, \a y, \a w, \a h) using fillStyle.
\sa fillStyle
*/
@@ -2301,14 +2314,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(const QV4::Functi
}
/*!
- \qmlmethod object QtQuick::Context2D::strokeRect(real x, real y, real w, real h)
- Stroke the specified rectangle's path using the strokeStyle, lineWidth, lineJoin,
- and (if appropriate) miterLimit attributes.
-
- \sa strokeStyle
- \sa lineWidth
- \sa lineJoin
- \sa miterLimit
+ \qmlmethod object QtQuick::Context2D::strokeRect(real x, real y, real w, real h)
+
+ Strokes the path of the rectangle specified by (\a x, \a y, \a w, \a h) using
+ strokeStyle, lineWidth, lineJoin, and (if appropriate) miterLimit attributes.
+
+ \sa strokeStyle, lineWidth, lineJoin, miterLimit
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2332,7 +2343,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(const QV4::Func
circle whose center is at the point (\a x, \a y) and whose radius is
\a radius.
- Both \c startAngle and \c endAngle are measured from the x-axis in radians.
+ Both \a startAngle and \a endAngle are measured from the x-axis in radians.
\image qml-item-canvas-arc.png
@@ -2439,10 +2450,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(const QV4::Funct
/*!
\qmlmethod object QtQuick::Context2D::bezierCurveTo(real cp1x, real cp1y, real cp2x, real cp2y, real x, real y)
- Adds a cubic bezier curve between the current position and the given endPoint using the control points specified by (\c cp1x, cp1y),
- and (\c cp2x, \c cp2y).
- After the curve is added, the current position is updated to be at the end point (\c x, \c y) of the curve.
+ Adds a cubic bezier curve between the current position and the given endPoint using the control points specified by (\a {cp1x}, \a {cp1y}),
+ and (\a {cp2x}, \a {cp2y}).
+ After the curve is added, the current position is updated to be at the end point (\a {x}, \a {y}) of the curve.
The following code produces the path shown below:
+
\code
ctx.strokeStyle = Qt.rgba(0, 0, 0, 1);
ctx.lineWidth = 1;
@@ -2451,7 +2463,9 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(const QV4::Funct
ctx.bezierCurveTo(-10, 90, 210, 90, 180, 0);
ctx.stroke();
\endcode
+
\image qml-item-canvas-bezierCurveTo.png
+
\sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-beziercurveto}{W3C 2d context standard for bezierCurveTo}
\sa {http://www.openrise.com/lab/FlowerPower/}{The beautiful flower demo by using bezierCurveTo}
*/
@@ -2550,7 +2564,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fill(const QV4::FunctionOb
/*!
\qmlmethod object QtQuick::Context2D::lineTo(real x, real y)
- Draws a line from the current position to the point (x, y).
+ Draws a line from the current position to the point at (\a x, \a y).
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2574,7 +2588,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(const QV4::Function
/*!
\qmlmethod object QtQuick::Context2D::moveTo(real x, real y)
- Creates a new subpath with the given point.
+ Creates a new subpath with a point at (\a x, \a y).
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2595,11 +2609,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(const QV4::Function
}
/*!
- \qmlmethod object QtQuick::Context2D::quadraticCurveTo(real cpx, real cpy, real x, real y)
+ \qmlmethod object QtQuick::Context2D::quadraticCurveTo(real cpx, real cpy, real x, real y)
- Adds a quadratic bezier curve between the current point and the endpoint (\c x, \c y) with the control point specified by (\c cpx, \c cpy).
+ Adds a quadratic bezier curve between the current point and the endpoint
+ (\a x, \a y) with the control point specified by (\a cpx, \a cpy).
- See \l{http://www.w3.org/TR/2dcontext/#dom-context-2d-quadraticcurveto}{W3C 2d context standard for quadraticCurveTo}
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-quadraticcurveto}{W3C 2d context standard for quadraticCurveTo}
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2623,9 +2638,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(const QV4
}
/*!
- \qmlmethod object QtQuick::Context2D::rect(real x, real y, real w, real h)
+ \qmlmethod object QtQuick::Context2D::rect(real x, real y, real w, real h)
- Adds a rectangle at position (\c x, \c y), with the given width \c w and height \c h, as a closed subpath.
+ Adds a rectangle at position (\a x, \a y), with the given width \a w and
+ height \a h, as a closed subpath.
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_rect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2640,10 +2656,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_rect(const QV4::FunctionOb
}
/*!
- \qmlmethod object QtQuick::Context2D::roundedRect(real x, real y, real w, real h, real xRadius, real yRadius)
+ \qmlmethod object QtQuick::Context2D::roundedRect(real x, real y, real w, real h, real xRadius, real yRadius)
- Adds the given rectangle rect with rounded corners to the path. The \c xRadius and \c yRadius arguments specify the radius of the
- ellipses defining the corners of the rounded rectangle.
+ Adds a rounded-corner rectangle, specified by (\a x, \a y, \a w, \a h), to the path.
+ The \a xRadius and \a yRadius arguments specify the radius of the
+ ellipses defining the corners of the rounded rectangle.
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_roundedRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2663,12 +2680,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_roundedRect(const QV4::Fun
}
/*!
- \qmlmethod object QtQuick::Context2D::ellipse(real x, real y, real w, real h)
+ \qmlmethod object QtQuick::Context2D::ellipse(real x, real y, real w, real h)
- Creates an ellipse within the bounding rectangle defined by its top-left corner at (\a x, \ y), width \a w and height \a h,
- and adds it to the path as a closed subpath.
+ Creates an ellipse within the bounding rectangle defined by its top-left
+ corner at (\a x, \a y), width \a w and height \a h, and adds it to the
+ path as a closed subpath.
- The ellipse is composed of a clockwise curve, starting and finishing at zero degrees (the 3 o'clock position).
+ The ellipse is composed of a clockwise curve, starting and finishing at
+ zero degrees (the 3 o'clock position).
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_ellipse(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2686,8 +2705,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_ellipse(const QV4::Functio
/*!
\qmlmethod object QtQuick::Context2D::text(string text, real x, real y)
- Adds the given \c text to the path as a set of closed subpaths created from the current context font supplied.
- The subpaths are positioned so that the left end of the text's baseline lies at the point specified by (\c x, \c y).
+ Adds the given \a text to the path as a set of closed subpaths created
+ from the current context font supplied.
+
+ The subpaths are positioned so that the left end of the text's baseline
+ lies at the point specified by (\a x, \a y).
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2712,9 +2734,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(const QV4::FunctionOb
Strokes the subpaths with the current stroke style.
- See \l{http://www.w3.org/TR/2dcontext/#dom-context-2d-stroke}{W3C 2d context standard for stroke}
-
- \sa strokeStyle
+ \sa strokeStyle, {http://www.w3.org/TR/2dcontext/#dom-context-2d-stroke}{W3C 2d context standard for stroke}
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
{
@@ -2730,7 +2750,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(const QV4::Function
/*!
\qmlmethod object QtQuick::Context2D::isPointInPath(real x, real y)
- Returns true if the given point is in the current path.
+ Returns \c true if the point (\a x, \a y) is in the current path.
\sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath}{W3C 2d context standard for isPointInPath}
*/
@@ -2948,7 +2968,9 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(const QV4::Functio
/*!
\qmlmethod object QtQuick::Context2D::fillText(text, x, y)
- Fills the given text at the given position.
+
+ Fills the specified \a text at the given position (\a x, \a y).
+
\sa font
\sa textAlign
\sa textBaseline
@@ -2972,13 +2994,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(const QV4::Functi
RETURN_RESULT(*thisObject);
}
/*!
- \qmlmethod object QtQuick::Context2D::strokeText(text, x, y)
- Strokes the given text at the given position.
- \sa font
- \sa textAlign
- \sa textBaseline
- \sa fillText
- */
+ \qmlmethod object QtQuick::Context2D::strokeText(text, x, y)
+
+ Strokes the given \a text at a position specified by (\a x, \a y).
+
+ \sa font
+ \sa textAlign
+ \sa textBaseline
+ \sa fillText
+*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
QV4::Scope scope(b);
@@ -3414,8 +3438,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(const QV4:
}
/*!
- \qmlmethod CanvasImageData QtQuick::Context2D::getImageData(real sx, real sy, real sw, real sh)
- Returns an CanvasImageData object containing the image data for the given rectangle of the canvas.
+ \qmlmethod CanvasImageData QtQuick::Context2D::getImageData(real x, real y, real w, real h)
+
+ Returns an CanvasImageData object containing the image data for the canvas
+ rectangle specified by (\a x, \a y, \a w, \a h).
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -3441,8 +3467,13 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(const QV4::Fu
}
/*!
- \qmlmethod object QtQuick::Context2D::putImageData(CanvasImageData imageData, real dx, real dy, real dirtyX, real dirtyY, real dirtyWidth, real dirtyHeight)
- Paints the data from the given ImageData object onto the canvas. If a dirty rectangle (\a dirtyX, \a dirtyY, \a dirtyWidth, \a dirtyHeight) is provided, only the pixels from that rectangle are painted.
+ \qmlmethod object QtQuick::Context2D::putImageData(CanvasImageData imageData, real dx, real dy, real dirtyX, real dirtyY, real dirtyWidth, real dirtyHeight)
+
+ Paints the data from the given \a imageData object onto the canvas at
+ (\a dx, \a dy).
+
+ If a dirty rectangle (\a dirtyX, \a dirtyY, \a dirtyWidth, \a dirtyHeight)
+ is provided, only the pixels from that rectangle are painted.
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -3535,16 +3566,18 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(const QV4::Fu
*/
/*!
- \qmlmethod CanvasGradient QtQuick::CanvasGradient::addColorStop(real offsetof, string color)
- Adds a color stop with the given color to the gradient at the given offset.
- 0.0 is the offset at one end of the gradient, 1.0 is the offset at the other end.
+ \qmlmethod CanvasGradient QtQuick::CanvasGradient::addColorStop(real offset, string color)
- For example:
- \code
- var gradient = ctx.createLinearGradient(0, 0, 100, 100);
- gradient.addColorStop(0.3, Qt.rgba(1, 0, 0, 1));
- gradient.addColorStop(0.7, 'rgba(0, 255, 255, 1');
- \endcode
+ Adds a color stop with the given \a color to the gradient at the given \a offset.
+ 0.0 is the offset at one end of the gradient, 1.0 is the offset at the other end.
+
+ For example:
+
+ \code
+ var gradient = ctx.createLinearGradient(0, 0, 100, 100);
+ gradient.addColorStop(0.3, Qt.rgba(1, 0, 0, 1));
+ gradient.addColorStop(0.7, 'rgba(0, 255, 255, 1');
+ \endcode
*/
QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index f4194ef13d..678c1361ba 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -90,6 +90,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAccessibleAttached : public QObject
Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged FINAL)
Q_PROPERTY(bool ignored READ ignored WRITE setIgnored NOTIFY ignoredChanged FINAL)
+ QML_NAMED_ELEMENT(Accessible)
+ QML_UNCREATABLE("Accessible is only available via attached properties.")
+ QML_ATTACHED(QQuickAccessibleAttached)
+
public:
Q_ENUMS(QAccessible::Role QAccessible::Event)
STATE_PROPERTY(checkable)
@@ -237,7 +241,6 @@ public:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickAccessibleAttached)
-QML_DECLARE_TYPEINFO(QQuickAccessibleAttached, QML_HAS_ATTACHED_PROPERTIES)
#endif // accessibility
diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h
index c7995cb7a8..e0276549e9 100644
--- a/src/quick/items/qquickanchors_p.h
+++ b/src/quick/items/qquickanchors_p.h
@@ -84,6 +84,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAnchors : public QObject
Q_PROPERTY(QQuickItem *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged)
Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged)
Q_PROPERTY(bool alignWhenCentered READ alignWhenCentered WRITE setAlignWhenCentered NOTIFY centerAlignedChanged)
+ QML_ANONYMOUS
public:
QQuickAnchors(QQuickItem *item, QObject *parent=nullptr);
diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp
index bebefc1b22..18d492cd68 100644
--- a/src/quick/items/qquickanimatedimage.cpp
+++ b/src/quick/items/qquickanimatedimage.cpp
@@ -140,6 +140,7 @@ QQuickAnimatedImage::QQuickAnimatedImage(QQuickItem *parent)
{
connect(this, &QQuickImageBase::cacheChanged, this, &QQuickAnimatedImage::onCacheChanged);
connect(this, &QQuickImageBase::currentFrameChanged, this, &QQuickAnimatedImage::frameChanged);
+ connect(this, &QQuickImageBase::currentFrameChanged, this, &QQuickAnimatedImage::currentFrameChanged);
connect(this, &QQuickImageBase::frameCountChanged, this, &QQuickAnimatedImage::frameCountChanged);
}
@@ -466,7 +467,7 @@ void QQuickAnimatedImage::movieUpdate()
if (d->movie) {
d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this)));
- emit currentFrameChanged();
+ emit QQuickImageBase::currentFrameChanged();
}
}
diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h
index ef5af6b387..7f2199fd2a 100644
--- a/src/quick/items/qquickanimatedimage_p.h
+++ b/src/quick/items/qquickanimatedimage_p.h
@@ -74,6 +74,7 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedImage : public QQuickImage
// read-only for AnimatedImage
Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
+ QML_NAMED_ELEMENT(AnimatedImage)
public:
QQuickAnimatedImage(QQuickItem *parent=nullptr);
@@ -101,6 +102,7 @@ Q_SIGNALS:
void playingChanged();
void pausedChanged();
void frameChanged();
+ void currentFrameChanged();
void frameCountChanged();
Q_REVISION(11) void speedChanged();
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index 18adb4e992..d22e77c8ad 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -532,7 +532,7 @@ void QQuickAnimatedSprite::setInterpolate(bool arg)
}
}
-void QQuickAnimatedSprite::setSource(QUrl arg)
+void QQuickAnimatedSprite::setSource(const QUrl &arg)
{
Q_D(QQuickAnimatedSprite);
diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h
index ff59591c9f..30f64e9def 100644
--- a/src/quick/items/qquickanimatedsprite_p.h
+++ b/src/quick/items/qquickanimatedsprite_p.h
@@ -92,6 +92,7 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem
Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged)
Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged)
+ QML_NAMED_ELEMENT(AnimatedSprite)
public:
explicit QQuickAnimatedSprite(QQuickItem *parent = nullptr);
@@ -122,7 +123,7 @@ Q_SIGNALS:
void runningChanged(bool arg);
void interpolateChanged(bool arg);
- void sourceChanged(QUrl arg);
+ void sourceChanged(const QUrl &arg);
void reverseChanged(bool arg);
void frameSyncChanged(bool arg);
void frameCountChanged(int arg);
@@ -148,7 +149,7 @@ public Q_SLOTS:
void setRunning(bool arg);
void setPaused(bool arg);
void setInterpolate(bool arg);
- void setSource(QUrl arg);
+ void setSource(const QUrl &arg);
void setReverse(bool arg);
void setFrameSync(bool arg);
void setFrameCount(int arg);
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 430fa1b094..462a44634e 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -327,7 +327,7 @@ void QQuickBorderImage::load()
QNetworkRequest req(d->url);
d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
qmlobject_connect(d->sciReply, QNetworkReply, SIGNAL(finished()),
- this, QQuickBorderImage, SLOT(sciRequestFinished()))
+ this, QQuickBorderImage, SLOT(sciRequestFinished()));
#endif
}
} else {
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index 61bd26ba83..515edb33da 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -67,6 +67,7 @@ class Q_AUTOTEST_EXPORT QQuickBorderImage : public QQuickImageBase
Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
// read-only for BorderImage
Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
+ QML_NAMED_ELEMENT(BorderImage)
public:
QQuickBorderImage(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index 0f4e7acc05..17dab7d121 100644
--- a/src/quick/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
@@ -86,7 +86,7 @@ public:
if (!border) {
border = new QQuickScaleGrid(q);
qmlobject_connect(border, QQuickScaleGrid, SIGNAL(borderChanged()),
- q, QQuickBorderImage, SLOT(doUpdate()))
+ q, QQuickBorderImage, SLOT(doUpdate()));
}
return border;
}
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 028b2b153d..ff4d9b0fd1 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE
class QQuickDragAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
Q_DECLARE_PUBLIC(QQuickDragAttached)
+ QML_ANONYMOUS
+
public:
static QQuickDragAttachedPrivate *get(QQuickDragAttached *attached) {
return static_cast<QQuickDragAttachedPrivate *>(QObjectPrivate::get(attached)); }
@@ -752,7 +754,11 @@ void QQuickDragAttached::cancel()
This signal is emitted when a drag finishes and the drag was started with the
\l startDrag() method or started automatically using the \l dragType property.
+ \a dropAction holds the action accepted by the target item.
+
The corresponding handler is \c onDragFinished.
+
+ \sa drop()
*/
Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedActions)
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index 094070aa2c..9dbaac18f9 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -172,6 +172,10 @@ class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged RESET resetThreshold)
//### consider drag and drop
+ QML_NAMED_ELEMENT(Drag)
+ QML_UNCREATABLE("Drag is only available via attached properties.")
+ QML_ATTACHED(QQuickDragAttached)
+
public:
QQuickDrag(QObject *parent=nullptr);
~QQuickDrag();
@@ -254,6 +258,9 @@ class QQuickDragAttached : public QObject
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
Q_PROPERTY(Qt::DropAction proposedAction READ proposedAction WRITE setProposedAction NOTIFY proposedActionChanged)
Q_PROPERTY(QQuickDrag::DragType dragType READ dragType WRITE setDragType NOTIFY dragTypeChanged)
+
+ QML_ANONYMOUS
+
public:
QQuickDragAttached(QObject *parent);
~QQuickDragAttached();
@@ -316,6 +323,5 @@ Q_SIGNALS:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickDrag)
-QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
#endif
diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp
index f96d6b6244..76be8cc261 100644
--- a/src/quick/items/qquickdroparea.cpp
+++ b/src/quick/items/qquickdroparea.cpp
@@ -211,7 +211,7 @@ qreal QQuickDropAreaDrag::y() const
/*!
\qmlsignal QtQuick::DropArea::positionChanged(DragEvent drag)
- This signal is emitted when the position of a drag has changed.
+ This signal is emitted when the position of a \a drag has changed.
The corresponding handler is \c onPositionChanged.
*/
@@ -313,7 +313,7 @@ void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *)
/*!
\qmlsignal QtQuick::DropArea::dropped(DragEvent drop)
- This signal is emitted when a drop event occurs within the bounds of
+ This signal is emitted when a \a drop event occurs within the bounds of
a DropArea.
The corresponding handler is \c onDropped.
diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h
index 2b2ace2eae..ee2deaa97a 100644
--- a/src/quick/items/qquickdroparea_p.h
+++ b/src/quick/items/qquickdroparea_p.h
@@ -80,6 +80,7 @@ class QQuickDropEvent : public QObject
Q_PROPERTY(QString text READ text)
Q_PROPERTY(QList<QUrl> urls READ urls)
Q_PROPERTY(QStringList formats READ formats)
+ QML_ANONYMOUS
public:
QQuickDropEvent(QQuickDropAreaPrivate *d, QDropEvent *event) : d(d), event(event) {}
@@ -125,6 +126,7 @@ class QQuickDropAreaDrag : public QObject
Q_PROPERTY(qreal x READ x NOTIFY positionChanged)
Q_PROPERTY(qreal y READ y NOTIFY positionChanged)
Q_PROPERTY(QObject *source READ source NOTIFY sourceChanged)
+ QML_ANONYMOUS
public:
QQuickDropAreaDrag(QQuickDropAreaPrivate *d, QObject *parent = 0);
~QQuickDropAreaDrag();
@@ -151,6 +153,7 @@ class Q_AUTOTEST_EXPORT QQuickDropArea : public QQuickItem
Q_PROPERTY(bool containsDrag READ containsDrag NOTIFY containsDragChanged)
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
Q_PROPERTY(QQuickDropAreaDrag *drag READ drag CONSTANT)
+ QML_NAMED_ELEMENT(DropArea)
public:
QQuickDropArea(QQuickItem *parent=0);
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index b0cfbaad6d..7d51a55a0c 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -41,6 +41,7 @@
#include <QtCore/qmap.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qtouchdevice_p.h>
+#include <QtGui/private/qevent_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/private/qquickwindow_p.h>
@@ -1828,6 +1829,7 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
// but that would require changing tst_qquickwindow::touchEvent_velocity(): it expects transformed velocity
bool anyPressOrReleaseInside = false;
+ bool anyStationaryWithModifiedPropertyInside = false;
bool anyGrabber = false;
QMatrix4x4 transformMatrix(QQuickItemPrivate::get(item)->windowToItemTransform());
for (int i = 0; i < m_pointCount; ++i) {
@@ -1860,6 +1862,8 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
anyPressOrReleaseInside = true;
const QTouchEvent::TouchPoint *tp = touchPointById(p->pointId());
if (tp) {
+ if (isInside && tp->d->stationaryWithModifiedProperty)
+ anyStationaryWithModifiedPropertyInside = true;
eventStates |= tp->state();
QTouchEvent::TouchPoint tpCopy = *tp;
tpCopy.setPos(item->mapFromScene(tpCopy.scenePos()));
@@ -1873,7 +1877,8 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
// Now touchPoints will have only points which are inside the item.
// But if none of them were just pressed inside, and the item has no other reason to care, ignore them anyway.
- if (eventStates == Qt::TouchPointStationary || touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering))
+ if ((eventStates == Qt::TouchPointStationary && !anyStationaryWithModifiedPropertyInside) ||
+ touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering))
return nullptr;
// if all points have the same state, set the event type accordingly
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index 1a3737091f..1d2ffefc9d 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -84,6 +84,7 @@ class QQuickKeyEvent : public QObject
Q_PROPERTY(int count READ count CONSTANT)
Q_PROPERTY(quint32 nativeScanCode READ nativeScanCode CONSTANT)
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ QML_ANONYMOUS
public:
QQuickKeyEvent()
@@ -135,6 +136,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseEvent : public QObject
Q_PROPERTY(bool isClick READ isClick CONSTANT)
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
Q_PROPERTY(int flags READ flags CONSTANT REVISION 11)
+ QML_ANONYMOUS
public:
QQuickMouseEvent()
@@ -201,6 +203,7 @@ class QQuickWheelEvent : public QObject
Q_PROPERTY(int modifiers READ modifiers CONSTANT)
Q_PROPERTY(bool inverted READ inverted CONSTANT)
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ QML_ANONYMOUS
public:
QQuickWheelEvent()
@@ -245,6 +248,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickCloseEvent : public QObject
{
Q_OBJECT
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ QML_ANONYMOUS
public:
QQuickCloseEvent() {}
@@ -271,6 +275,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
Q_PROPERTY(QObject *exclusiveGrabber READ exclusiveGrabber WRITE setExclusiveGrabber)
+ QML_NAMED_ELEMENT(EventPoint)
+ QML_UNCREATABLE("EventPoint is only available as a member of PointerEvent.")
+ QML_ADDED_IN_MINOR_VERSION(12)
+
public:
enum State {
Pressed = Qt::TouchPointPressed,
@@ -362,6 +370,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventTouchPoint : public QQuickEventPoint
Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters)
Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId)
+ QML_NAMED_ELEMENT(EventTouchPoint)
+ QML_UNCREATABLE("EventTouchPoint is only available as a member of PointerEvent.")
+ QML_ADDED_IN_MINOR_VERSION(12)
+
public:
QQuickEventTouchPoint(QQuickPointerTouchEvent *parent);
@@ -391,6 +403,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerEvent : public QObject
Q_PROPERTY(Qt::MouseButtons button READ button CONSTANT)
Q_PROPERTY(Qt::MouseButtons buttons READ buttons CONSTANT)
+ QML_NAMED_ELEMENT(PointerEvent)
+ QML_UNCREATABLE("PointerEvent is only available as a parameter of several signals in PointerHandler")
+ QML_ADDED_IN_MINOR_VERSION(12)
+
public:
QQuickPointerEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
: QObject(parent)
@@ -482,6 +498,11 @@ protected:
class Q_QUICK_PRIVATE_EXPORT QQuickPointerMouseEvent : public QQuickSinglePointEvent
{
Q_OBJECT
+
+ QML_NAMED_ELEMENT(PointerMouseEvent)
+ QML_UNCREATABLE("PointerMouseEvent is only available as a parameter of several signals in PointerHandler")
+ QML_ADDED_IN_MINOR_VERSION(12)
+
public:
QQuickPointerMouseEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
: QQuickSinglePointEvent(parent, device) { }
@@ -502,6 +523,11 @@ public:
class Q_QUICK_PRIVATE_EXPORT QQuickPointerTouchEvent : public QQuickPointerEvent
{
Q_OBJECT
+
+ QML_NAMED_ELEMENT(PointerTouchEvent)
+ QML_UNCREATABLE("PointerTouchEvent is only available as a parameter of several signals in PointerHandler")
+ QML_ADDED_IN_MINOR_VERSION(12)
+
public:
QQuickPointerTouchEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
: QQuickPointerEvent(parent, device)
@@ -623,6 +649,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerDevice : public QObject
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId CONSTANT)
+ QML_NAMED_ELEMENT(PointerDevice)
+ QML_UNCREATABLE("PointerDevice is only available as a property of PointerEvent.")
+ QML_ADDED_IN_MINOR_VERSION(12)
+
public:
enum DeviceType : qint16 {
UnknownDevice = 0x0000,
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index cf3cd9f48e..d9ec7de611 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -266,9 +266,9 @@ void QQuickFlickablePrivate::init()
QQml_setParent_noEvent(contentItem, q);
contentItem->setParentItem(q);
qmlobject_connect(&timeline, QQuickTimeLine, SIGNAL(completed()),
- q, QQuickFlickable, SLOT(timelineCompleted()))
+ q, QQuickFlickable, SLOT(timelineCompleted()));
qmlobject_connect(&velocityTimeline, QQuickTimeLine, SIGNAL(completed()),
- q, QQuickFlickable, SLOT(velocityTimelineCompleted()))
+ q, QQuickFlickable, SLOT(velocityTimelineCompleted()));
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setAcceptTouchEvents(false); // rely on mouse events synthesized from touch
q->setFiltersChildMouseEvents(true);
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index c54ed5ce71..2d8d4a5e9a 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -114,6 +114,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem
Q_PROPERTY(QQmlListProperty<QObject> flickableData READ flickableData)
Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren)
Q_CLASSINFO("DefaultProperty", "flickableData")
+ QML_NAMED_ELEMENT(Flickable)
public:
QQuickFlickable(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 835c54170f..1ff55dae90 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -284,6 +284,7 @@ class QQuickFlickableVisibleArea : public QObject
Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged)
Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged)
Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged)
+ QML_ANONYMOUS
public:
QQuickFlickableVisibleArea(QQuickFlickable *parent=nullptr);
diff --git a/src/quick/items/qquickflickablebehavior_p.h b/src/quick/items/qquickflickablebehavior_p.h
index ae7fe71359..fbce62f075 100644
--- a/src/quick/items/qquickflickablebehavior_p.h
+++ b/src/quick/items/qquickflickablebehavior_p.h
@@ -93,6 +93,11 @@
#define QML_FLICK_MULTIFLICK_THRESHOLD 1250
#endif
+// If the time (ms) between the last move and the release exceeds this, then velocity will be zero.
+#ifndef QML_FLICK_VELOCITY_DECAY_TIME
+#define QML_FLICK_VELOCITY_DECAY_TIME 50
+#endif
+
// Multiflick acceleration minimum contentSize/viewSize ratio
#ifndef QML_FLICK_MULTIFLICK_RATIO
#define QML_FLICK_MULTIFLICK_RATIO 10
diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h
index d70cd02d35..42c632a33c 100644
--- a/src/quick/items/qquickflipable_p.h
+++ b/src/quick/items/qquickflipable_p.h
@@ -71,6 +71,7 @@ class Q_AUTOTEST_EXPORT QQuickFlipable : public QQuickItem
Q_PROPERTY(QQuickItem *front READ front WRITE setFront NOTIFY frontChanged)
Q_PROPERTY(QQuickItem *back READ back WRITE setBack NOTIFY backChanged)
Q_PROPERTY(Side side READ side NOTIFY sideChanged)
+ QML_NAMED_ELEMENT(Flipable)
//### flipAxis
//### flipRotation
public:
diff --git a/src/quick/items/qquickfocusscope_p.h b/src/quick/items/qquickfocusscope_p.h
index af750fc127..c32fa93cd9 100644
--- a/src/quick/items/qquickfocusscope_p.h
+++ b/src/quick/items/qquickfocusscope_p.h
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QQuickFocusScope : public QQuickItem
{
Q_OBJECT
+ QML_NAMED_ELEMENT(FocusScope)
public:
QQuickFocusScope(QQuickItem *parent=nullptr);
virtual ~QQuickFocusScope();
diff --git a/src/quick/items/qquickgraphicsinfo_p.h b/src/quick/items/qquickgraphicsinfo_p.h
index f0a18c29cc..066a419c37 100644
--- a/src/quick/items/qquickgraphicsinfo_p.h
+++ b/src/quick/items/qquickgraphicsinfo_p.h
@@ -75,6 +75,11 @@ class QQuickGraphicsInfo : public QObject
Q_PROPERTY(OpenGLContextProfile profile READ profile NOTIFY profileChanged FINAL)
Q_PROPERTY(RenderableType renderableType READ renderableType NOTIFY renderableTypeChanged FINAL)
+ QML_NAMED_ELEMENT(GraphicsInfo)
+ QML_ADDED_IN_MINOR_VERSION(8)
+ QML_UNCREATABLE("GraphicsInfo is only available via attached properties.")
+ QML_ATTACHED(QQuickGraphicsInfo)
+
public:
enum GraphicsApi {
Unknown = QSGRendererInterface::Unknown,
@@ -168,6 +173,4 @@ private:
QT_END_NAMESPACE
-QML_DECLARE_TYPEINFO(QQuickGraphicsInfo, QML_HAS_ATTACHED_PROPERTIES)
-
#endif // QQUICKGRAPHICSINFO_P_H
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index fecfa5fd2d..e69e9cff46 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -1761,7 +1761,7 @@ void QQuickGridView::setSnapMode(SnapMode mode)
\list
\li The view is first created
- \li The view's \l model changes
+ \li The view's \l model changes in such a way that the visible delegates are completely replaced
\li The view's \l model is \l {QAbstractItemModel::reset()}{reset}, if the model is a QAbstractItemModel subclass
\endlist
@@ -1779,6 +1779,28 @@ void QQuickGridView::setSnapMode(SnapMode mode)
When the view is initialized, the view will create all the necessary items for the view,
then animate them to their correct positions within the view over one second.
+ However when scrolling the view later, the populate transition does not
+ run, even though delegates are being instantiated as they become visible.
+ When the model changes in a way that new delegates become visible, the
+ \l add transition is the one that runs. So you should not depend on the
+ \c populate transition to initialize properties in the delegate, because it
+ does not apply to every delegate. If your animation sets the \c to value of
+ a property, the property should initially have the \c to value, and the
+ animation should set the \c from value in case it is animated:
+
+ \code
+ GridView {
+ ...
+ delegate: Rectangle {
+ opacity: 1 // not necessary because it's the default; but don't set 0
+ ...
+ }
+ populate: Transition {
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 1000 }
+ }
+ }
+ \endcode
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h
index 7daeaf41a1..9072e5f269 100644
--- a/src/quick/items/qquickgridview_p.h
+++ b/src/quick/items/qquickgridview_p.h
@@ -73,6 +73,8 @@ class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
Q_CLASSINFO("DefaultProperty", "data")
+ QML_NAMED_ELEMENT(GridView)
+ QML_ATTACHED(QQuickGridViewAttached)
public:
enum Flow {
@@ -136,6 +138,5 @@ public:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickGridView)
-QML_DECLARE_TYPEINFO(QQuickGridView, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKGRIDVIEW_P_H
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index c7e7ccea55..840cfe15da 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -676,13 +676,13 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
int xOffset = 0;
if (d->hAlign == QQuickImage::AlignHCenter)
- xOffset = qCeil((width() - pixWidth) / 2.);
+ xOffset = (width() - pixWidth) / 2;
else if (d->hAlign == QQuickImage::AlignRight)
xOffset = qCeil(width() - pixWidth);
int yOffset = 0;
if (d->vAlign == QQuickImage::AlignVCenter)
- yOffset = qCeil((height() - pixHeight) / 2.);
+ yOffset = (height() - pixHeight) / 2;
else if (d->vAlign == QQuickImage::AlignBottom)
yOffset = qCeil(height() - pixHeight);
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index 257cde5313..f7e652cdcc 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -68,6 +68,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickImage : public QQuickImageBase
Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged)
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged REVISION 3)
Q_PROPERTY(bool autoTransform READ autoTransform WRITE setAutoTransform NOTIFY autoTransformChanged REVISION 5)
+ QML_NAMED_ELEMENT(Image)
public:
QQuickImage(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 8cd59c8cea..d1d01ad27d 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -71,6 +71,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickImageBase : public QQuickImplicitSizeItem
Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged REVISION 14)
Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged REVISION 14)
+ QML_NAMED_ELEMENT(ImageBase);
+ QML_ADDED_IN_MINOR_VERSION(14)
+ QML_UNCREATABLE("ImageBase is an abstract base class.")
+
public:
QQuickImageBase(QQuickItem *parent=nullptr);
~QQuickImageBase();
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 52a1d59e77..796ab6cdd7 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -5083,7 +5083,7 @@ QQuickStateGroup *QQuickItemPrivate::_states()
if (!componentComplete)
_stateGroup->classBegin();
qmlobject_connect(_stateGroup, QQuickStateGroup, SIGNAL(stateChanged(QString)),
- q, QQuickItem, SIGNAL(stateChanged(QString)))
+ q, QQuickItem, SIGNAL(stateChanged(QString)));
}
return _stateGroup;
@@ -5686,6 +5686,7 @@ void QQuickItem::setRotation(qreal r)
color: "red"
x: 25; y: 25; width: 50; height: 50
scale: 1.4
+ transformOrigin: Item.TopLeft
}
}
\endqml
@@ -8489,7 +8490,7 @@ void QQuickItemLayer::setMipmap(bool mipmap)
\note ShaderEffectSource.RGB and ShaderEffectSource.Alpha should
be used with caution, as support for these formats in the underlying
- hardare and driver is often not present.
+ hardware and driver is often not present.
\sa {Item Layers}
*/
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 394a5adb8c..8c04ced11b 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -58,6 +58,7 @@ class QQuickTransformPrivate;
class Q_QUICK_EXPORT QQuickTransform : public QObject
{
Q_OBJECT
+ QML_ANONYMOUS
public:
explicit QQuickTransform(QObject *parent = nullptr);
~QQuickTransform() override;
@@ -150,6 +151,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_CLASSINFO("DefaultProperty", "data")
Q_CLASSINFO("qt_QmlJSWrapperFactoryMethod", "_q_createJSWrapper(QV4::ExecutionEngine*)")
+ QML_NAMED_ELEMENT(Item)
public:
enum Flag {
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 3e8feec4bf..7c3325fd90 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -152,6 +152,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
Q_PROPERTY(QQmlComponent *effect READ effect WRITE setEffect NOTIFY effectChanged)
Q_PROPERTY(QQuickShaderEffectSource::TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged)
Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged)
+ QML_ANONYMOUS
public:
QQuickItemLayer(QQuickItem *item);
@@ -715,6 +716,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickKeyNavigationAttached : public QObject, publi
Q_PROPERTY(QQuickItem *backtab READ backtab WRITE setBacktab NOTIFY backtabChanged)
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
+ QML_NAMED_ELEMENT(KeyNavigation)
+ QML_UNCREATABLE("KeyNavigation is only available via attached properties.")
+ QML_ATTACHED(QQuickKeyNavigationAttached)
+
public:
QQuickKeyNavigationAttached(QObject * = nullptr);
@@ -760,6 +765,10 @@ class QQuickLayoutMirroringAttached : public QObject
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled RESET resetEnabled NOTIFY enabledChanged)
Q_PROPERTY(bool childrenInherit READ childrenInherit WRITE setChildrenInherit NOTIFY childrenInheritChanged)
+ QML_NAMED_ELEMENT(LayoutMirroring)
+ QML_UNCREATABLE("LayoutMirroring is only available via attached properties.")
+ QML_ATTACHED(QQuickLayoutMirroringAttached)
+
public:
explicit QQuickLayoutMirroringAttached(QObject *parent = nullptr);
@@ -784,6 +793,11 @@ class QQuickEnterKeyAttached : public QObject
Q_OBJECT
Q_PROPERTY(Qt::EnterKeyType type READ type WRITE setType NOTIFY typeChanged)
+ QML_NAMED_ELEMENT(EnterKey)
+ QML_UNCREATABLE("EnterKey is only available via attached properties")
+ QML_ADDED_IN_MINOR_VERSION(6)
+ QML_ATTACHED(QQuickEnterKeyAttached)
+
public:
explicit QQuickEnterKeyAttached(QObject *parent = nullptr);
@@ -829,6 +843,10 @@ class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
Q_PROPERTY(QQmlListProperty<QQuickItem> forwardTo READ forwardTo)
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
+ QML_NAMED_ELEMENT(Keys)
+ QML_UNCREATABLE("Keys is only available via attached properties")
+ QML_ATTACHED(QQuickKeysAttached)
+
public:
QQuickKeysAttached(QObject *parent=nullptr);
~QQuickKeysAttached() override;
@@ -984,12 +1002,8 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickItemLayer)
#endif
QML_DECLARE_TYPE(QQuickKeysAttached)
-QML_DECLARE_TYPEINFO(QQuickKeysAttached, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickKeyNavigationAttached)
-QML_DECLARE_TYPEINFO(QQuickKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickLayoutMirroringAttached)
-QML_DECLARE_TYPEINFO(QQuickLayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickEnterKeyAttached)
-QML_DECLARE_TYPEINFO(QQuickEnterKeyAttached, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKITEM_P_H
diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h
index b803455f12..28c18c874d 100644
--- a/src/quick/items/qquickitemanimation_p.h
+++ b/src/quick/items/qquickitemanimation_p.h
@@ -66,6 +66,7 @@ class Q_AUTOTEST_EXPORT QQuickParentAnimation : public QQuickAnimationGroup
Q_PROPERTY(QQuickItem *target READ target WRITE setTargetObject NOTIFY targetChanged)
Q_PROPERTY(QQuickItem *newParent READ newParent WRITE setNewParent NOTIFY newParentChanged)
Q_PROPERTY(QQuickItem *via READ via WRITE setVia NOTIFY viaChanged)
+ QML_NAMED_ELEMENT(ParentAnimation)
public:
QQuickParentAnimation(QObject *parent=nullptr);
@@ -100,6 +101,7 @@ class Q_AUTOTEST_EXPORT QQuickAnchorAnimation : public QQuickAbstractAnimation
Q_PROPERTY(QQmlListProperty<QQuickItem> targets READ targets)
Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ QML_NAMED_ELEMENT(AnchorAnimation)
public:
QQuickAnchorAnimation(QObject *parent=nullptr);
@@ -143,6 +145,7 @@ class Q_AUTOTEST_EXPORT QQuickPathAnimation : public QQuickAbstractAnimation
Q_PROPERTY(int orientationEntryDuration READ orientationEntryDuration WRITE setOrientationEntryDuration NOTIFY orientationEntryDurationChanged)
Q_PROPERTY(int orientationExitDuration READ orientationExitDuration WRITE setOrientationExitDuration NOTIFY orientationExitDurationChanged)
Q_PROPERTY(qreal endRotation READ endRotation WRITE setEndRotation NOTIFY endRotationChanged)
+ QML_NAMED_ELEMENT(PathAnimation)
public:
QQuickPathAnimation(QObject *parent=nullptr);
diff --git a/src/quick/items/qquickitemgrabresult.h b/src/quick/items/qquickitemgrabresult.h
index 3dc10e2d75..c92a8c52f4 100644
--- a/src/quick/items/qquickitemgrabresult.h
+++ b/src/quick/items/qquickitemgrabresult.h
@@ -45,6 +45,7 @@
#include <QtCore/QUrl>
#include <QtGui/QImage>
#include <QtQml/QJSValue>
+#include <QtQml/qqml.h>
#include <QtQuick/qtquickglobal.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +61,8 @@ class Q_QUICK_EXPORT QQuickItemGrabResult : public QObject
Q_PROPERTY(QImage image READ image CONSTANT)
Q_PROPERTY(QUrl url READ url CONSTANT)
+ QML_ANONYMOUS
+
public:
QImage image() const;
QUrl url() const;
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 6db664f705..f7943630c4 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -175,327 +175,217 @@ static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject
return QQmlPrivate::IncompatibleObject;
}
-static void qt_quickitems_defineModule(const char *uri, int major, int minor)
+static void qt_quickitems_defineModule()
{
+ const char *uri = "QtQuick";
+ const int major = 2;
+
QQmlPrivate::RegisterAutoParent autoparent = { 0, &qquickitem_autoParent };
QQmlPrivate::qmlregister(QQmlPrivate::AutoParentRegistration, &autoparent);
- qmlRegisterModule(uri, 2, 15);
-
-#if !QT_CONFIG(quick_animatedimage)
- qmlRegisterTypeNotAvailable(uri,major,minor,"AnimatedImage", QCoreApplication::translate("QQuickAnimatedImage","Qt was built without support for QMovie"));
-#else
- qmlRegisterType<QQuickAnimatedImage>(uri,major,minor,"AnimatedImage");
-#endif
- qmlRegisterType<QQuickBorderImage>(uri,major,minor,"BorderImage");
- qmlRegisterType<QQuickFlickable>(uri,major,minor,"Flickable");
-#if QT_CONFIG(quick_flipable)
- qmlRegisterType<QQuickFlipable>(uri,major,minor,"Flipable");
-#endif
-// qmlRegisterType<QQuickFocusPanel>(uri,major,minor,"FocusPanel");
- qmlRegisterType<QQuickFocusScope>(uri,major,minor,"FocusScope");
- qmlRegisterType<QQuickGradient>(uri,major,minor,"Gradient");
- qmlRegisterType<QQuickGradientStop>(uri,major,minor,"GradientStop");
-#if QT_CONFIG(quick_positioners)
- qmlRegisterType<QQuickColumn>(uri,major,minor,"Column");
- qmlRegisterType<QQuickFlow>(uri,major,minor,"Flow");
- qmlRegisterType<QQuickGrid>(uri,major,minor,"Grid");
- qmlRegisterUncreatableType<QQuickBasePositioner>(uri,major,minor,"Positioner",
- QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
- qmlRegisterType<QQuickRow>(uri,major,minor,"Row");
-#endif
-#if QT_CONFIG(quick_gridview)
- qmlRegisterType<QQuickGridView>(uri,major,minor,"GridView");
-#endif
- qmlRegisterType<QQuickImage>(uri,major,minor,"Image");
- qmlRegisterType<QQuickItem>(uri,major,minor,"Item");
-#if QT_CONFIG(quick_listview)
- qmlRegisterType<QQuickListView>(uri,major,minor,"ListView");
- qmlRegisterType<QQuickViewSection>(uri,major,minor,"ViewSection");
-#endif
- qmlRegisterType<QQuickLoader>(uri,major,minor,"Loader");
- qmlRegisterType<QQuickMouseArea>(uri,major,minor,"MouseArea");
-#if QT_CONFIG(quick_path)
- qmlRegisterType<QQuickPath>(uri,major,minor,"Path");
- qmlRegisterType<QQuickPathAttribute>(uri,major,minor,"PathAttribute");
- qmlRegisterType<QQuickPathCubic>(uri,major,minor,"PathCubic");
- qmlRegisterType<QQuickPathLine>(uri,major,minor,"PathLine");
- qmlRegisterType<QQuickPathPercent>(uri,major,minor,"PathPercent");
- qmlRegisterType<QQuickPathQuad>(uri,major,minor,"PathQuad");
- qmlRegisterType<QQuickPathCatmullRomCurve>("QtQuick",2,0,"PathCurve");
- qmlRegisterType<QQuickPathArc>("QtQuick",2,0,"PathArc");
- qmlRegisterType<QQuickPathSvg>("QtQuick",2,0,"PathSvg");
- qmlRegisterType<QQuickPath, 14>(uri, 2, 14, "Path");
- qmlRegisterType<QQuickPathPolyline>("QtQuick", 2, 14, "PathPolyline");
- qmlRegisterType<QQuickPathMultiline>("QtQuick", 2, 14, "PathMultiline");
-#endif
-#if QT_CONFIG(quick_pathview)
- qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView");
-#endif
- qmlRegisterType<QQuickRectangle>(uri,major,minor,"Rectangle");
-#if QT_CONFIG(quick_repeater)
- qmlRegisterType<QQuickRepeater>(uri,major,minor,"Repeater");
-#endif
- qmlRegisterType<QQuickTranslate>(uri,major,minor,"Translate");
- qmlRegisterType<QQuickRotation>(uri,major,minor,"Rotation");
- qmlRegisterType<QQuickScale>(uri,major,minor,"Scale");
- qmlRegisterType<QQuickMatrix4x4>(uri,2,3,"Matrix4x4");
- qmlRegisterType<QQuickText>(uri,major,minor,"Text");
- qmlRegisterType<QQuickTextEdit>(uri,major,minor,"TextEdit");
- qmlRegisterType<QQuickTextEdit,1>(uri,2,1,"TextEdit");
- qmlRegisterType<QQuickTextInput>(uri,major,minor,"TextInput");
- qmlRegisterType<QQuickTextInput,2>(uri,2,2,"TextInput");
- qmlRegisterType<QQuickTextInput,4>(uri,2,4,"TextInput");
- qmlRegisterAnonymousType<QQuickItemGrabResult>(uri, major);
-#if QT_CONFIG(quick_shadereffect)
- qmlRegisterAnonymousType<QQuickItemLayer>(uri, major);
-#endif
- qmlRegisterAnonymousType<QQuickAnchors>(uri, major);
- qmlRegisterAnonymousType<QQuickKeyEvent>(uri, major);
- qmlRegisterAnonymousType<QQuickMouseEvent>(uri, major);
- qmlRegisterAnonymousType<QQuickWheelEvent>(uri, major);
- qmlRegisterAnonymousType<QQuickCloseEvent>(uri, major);
- qmlRegisterAnonymousType<QQuickTransform>(uri, major);
-#if QT_CONFIG(quick_path)
- qmlRegisterAnonymousType<QQuickPathElement>(uri, major);
- qmlRegisterAnonymousType<QQuickCurve>(uri, major);
-#endif
- qmlRegisterAnonymousType<QQuickScaleGrid>(uri, major);
- qmlRegisterAnonymousType<QQuickTextLine>(uri, major);
- qmlRegisterAnonymousType<QQuickPen>(uri, major);
- qmlRegisterAnonymousType<QQuickFlickableVisibleArea>(uri, major);
qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine");
+ qRegisterMetaType<QPointingDeviceUniqueId>("QPointingDeviceUniqueId");
+ qRegisterMetaType<QQuickHandlerPoint>();
- qmlRegisterAnonymousType<QQuickTextDocument>(uri, major);
-
-
- qmlRegisterUncreatableType<QQuickKeyNavigationAttached>(uri,major,minor,"KeyNavigation",QQuickKeyNavigationAttached::tr("KeyNavigation is only available via attached properties"));
- qmlRegisterUncreatableType<QQuickKeysAttached>(uri,major,minor,"Keys",QQuickKeysAttached::tr("Keys is only available via attached properties"));
- qmlRegisterUncreatableType<QQuickLayoutMirroringAttached>(uri,major,minor,"LayoutMirroring", QQuickLayoutMirroringAttached::tr("LayoutMirroring is only available via attached properties"));
-#if QT_CONFIG(quick_viewtransitions)
- qmlRegisterUncreatableType<QQuickViewTransitionAttached>(uri,major,minor,"ViewTransition",QQuickViewTransitionAttached::tr("ViewTransition is only available via attached properties"));
-#endif
+ qmlRegisterModule(uri, major, 15);
+
+ // Core QtQuick types
+ qmlRegisterTypesAndRevisions<
+ QPointingDeviceUniqueIdForeign,
+ QQuickAnchorAnimation,
+ QQuickAnchorChanges,
+ QQuickAnchors,
+ QQuickAnchorSet,
+ QQuickBorderImage,
+ QQuickEnterKeyAttached,
+ QQuickEventPoint,
+ QQuickEventTouchPoint,
+ QQuickFlickable,
+ QQuickFlickableVisibleArea,
+ QQuickFocusScope,
+ QQuickGradient,
+ QQuickGradientStop,
+ QQuickGraphicsInfo,
+ QQuickImage,
+ QQuickImageBase,
+ QQuickItem,
+ QQuickItemGrabResult,
+ QQuickKeyNavigationAttached,
+ QQuickKeysAttached,
+ QQuickLayoutMirroringAttached,
+ QQuickLoader,
+ QQuickMatrix4x4,
+ QQuickMouseArea,
+ QQuickMultiPointTouchArea,
+ QQuickPaintedItem,
+ QQuickParentAnimation,
+ QQuickParentChange,
+ QQuickPen,
+ QQuickPinch,
+ QQuickPinchArea,
+ QQuickPointerDevice,
+ QQuickRectangle,
+ QQuickRotation,
+ QQuickScale,
+ QQuickScaleGrid,
+ QQuickTouchPoint,
+ QQuickTransform,
+ QQuickTranslate
+ >(uri, major);
+
+ // text-related types
+ qmlRegisterTypesAndRevisions<
+ QQuickText,
+ QQuickTextDocument,
+ QQuickTextEdit,
+ QQuickTextInput,
+ QQuickTextLine
+ >(uri, major);
+
+ // events
+ qmlRegisterTypesAndRevisions<
+ QQuickCloseEvent,
+ QQuickGrabGestureEvent,
+ QQuickKeyEvent,
+ QQuickMouseEvent,
+ QQuickPinchEvent,
+ QQuickPointerEvent,
+ QQuickPointerMouseEvent,
+ QQuickPointerTouchEvent,
+ QQuickWheelEvent
+ >(uri, major);
- qmlRegisterType<QQuickPinchArea>(uri,major,minor,"PinchArea");
- qmlRegisterType<QQuickPinch>(uri,major,minor,"Pinch");
- qmlRegisterAnonymousType<QQuickPinchEvent>(uri, major);
+ // Input Handlers are part of QtQuick, not a separate module, since 5.12
+ qmlRegisterTypesAndRevisions<
+ QQuickDragHandler,
+ QQuickHoverHandler,
+ QQuickPinchHandler,
+ QQuickPointerHandler,
+ QQuickPointHandler,
+ QQuickTapHandler
+ >(uri, major);
-#if QT_CONFIG(quick_shadereffect)
- qmlRegisterType<QQuickShaderEffectSource>("QtQuick", 2, 0, "ShaderEffectSource");
- qmlRegisterUncreatableType<QQuickShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QQuickShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh."));
- qmlRegisterType<QQuickGridMesh>("QtQuick", 2, 0, "GridMesh");
- qmlRegisterType<QQuickShaderEffect>("QtQuick", 2, 0, "ShaderEffect");
+#if QT_CONFIG(accessibility)
+ qmlRegisterTypesAndRevisions<QQuickAccessibleAttached>(uri, major);
#endif
- qmlRegisterUncreatableType<QQuickPaintedItem>("QtQuick", 2, 0, "PaintedItem", QQuickPaintedItem::tr("Cannot create instance of abstract class PaintedItem"));
-
-#if QT_CONFIG(quick_canvas)
- qmlRegisterType<QQuickCanvasItem>("QtQuick", 2, 0, "Canvas");
+#if QT_CONFIG(opengl)
+ qmlRegisterTypesAndRevisions<QQuickOpenGLInfo>(uri, major);
#endif
-#if QT_CONFIG(quick_sprite)
- qmlRegisterType<QQuickSprite>("QtQuick", 2, 0, "Sprite");
- qmlRegisterType<QQuickAnimatedSprite>("QtQuick", 2, 0, "AnimatedSprite");
- qmlRegisterType<QQuickSpriteSequence>("QtQuick", 2, 0, "SpriteSequence");
+#if QT_CONFIG(quick_animatedimage)
+ qmlRegisterTypesAndRevisions<QQuickAnimatedImage>(uri, major);
+#else
+ qmlRegisterTypeNotAvailable(
+ uri, major, 15, "AnimatedImage",
+ QCoreApplication::translate("QQuickAnimatedImage",
+ "Qt was built without support for QMovie"));
#endif
- qmlRegisterType<QQuickParentChange>(uri, major, minor,"ParentChange");
- qmlRegisterType<QQuickAnchorChanges>(uri, major, minor,"AnchorChanges");
- qmlRegisterAnonymousType<QQuickAnchorSet>(uri, major);
- qmlRegisterType<QQuickAnchorAnimation>(uri, major, minor,"AnchorAnimation");
- qmlRegisterType<QQuickParentAnimation>(uri, major, minor,"ParentAnimation");
-#if QT_CONFIG(quick_path)
- qmlRegisterType<QQuickPathAnimation>("QtQuick",2,0,"PathAnimation");
- qmlRegisterType<QQuickPathInterpolator>("QtQuick",2,0,"PathInterpolator");
+#if QT_CONFIG(quick_canvas)
+ qmlRegisterTypesAndRevisions<QQuickCanvasItem>(uri, major);
#endif
#if QT_CONFIG(quick_draganddrop)
- qmlRegisterType<QQuickDropArea>("QtQuick", 2, 0, "DropArea");
- qmlRegisterAnonymousType<QQuickDropEvent>(uri, 2);
- qmlRegisterAnonymousType<QQuickDropAreaDrag>(uri, 2);
- qmlRegisterUncreatableType<QQuickDrag>("QtQuick", 2, 0, "Drag", QQuickDragAttached::tr("Drag is only available via attached properties"));
+ qmlRegisterTypesAndRevisions<
+ QQuickDropEvent,
+ QQuickDrag,
+ QQuickDropArea,
+ QQuickDropAreaDrag,
+ QQuickDragAttached,
+ QQuickDragAxis
+ >(uri, major);
#endif
- qmlRegisterType<QQuickMultiPointTouchArea>("QtQuick", 2, 0, "MultiPointTouchArea");
- qmlRegisterType<QQuickTouchPoint>("QtQuick", 2, 0, "TouchPoint");
- qmlRegisterUncreatableType<QQuickGrabGestureEvent>(uri,major,minor, "GestureEvent",
- QQuickMouseEvent::tr("GestureEvent is only available in the context of handling the gestureStarted signal from MultiPointTouchArea"));
-
-#if QT_CONFIG(accessibility)
- qmlRegisterUncreatableType<QQuickAccessibleAttached>("QtQuick", 2, 0, "Accessible",QQuickAccessibleAttached::tr("Accessible is only available via attached properties"));
+#if QT_CONFIG(quick_flipable)
+ qmlRegisterTypesAndRevisions<QQuickFlipable>(uri, major);
#endif
- qmlRegisterType<QQuickItem, 1>(uri, 2, 1,"Item");
#if QT_CONFIG(quick_positioners)
- qmlRegisterType<QQuickGrid, 1>(uri, 2, 1, "Grid");
-#endif
-#if QT_CONFIG(quick_itemview)
- const char *itemViewName = "ItemView";
- const QString itemViewMessage = QQuickItemView::tr("ItemView is an abstract base class");
- qmlRegisterUncreatableType<QQuickItemView, 1>(uri, 2, 1, itemViewName, itemViewMessage);
- qmlRegisterUncreatableType<QQuickItemView, 3>(uri, 2, 3, itemViewName, itemViewMessage);
-#endif
-#if QT_CONFIG(quick_listview)
- qmlRegisterType<QQuickListView, 1>(uri, 2, 1, "ListView");
-#endif
-#if QT_CONFIG(quick_gridview)
- qmlRegisterType<QQuickGridView, 1>(uri, 2, 1, "GridView");
+ qmlRegisterTypesAndRevisions<
+ QQuickBasePositioner,
+ QQuickColumn,
+ QQuickFlow,
+ QQuickGrid,
+ QQuickRow
+ >(uri, major);
#endif
- qmlRegisterType<QQuickTextEdit, 1>(uri, 2, 1, "TextEdit");
- qmlRegisterType<QQuickText, 2>(uri, 2, 2, "Text");
- qmlRegisterType<QQuickTextEdit, 2>(uri, 2, 2, "TextEdit");
-
- qmlRegisterType<QQuickText, 3>(uri, 2, 3, "Text");
- qmlRegisterType<QQuickTextEdit, 3>(uri, 2, 3, "TextEdit");
- qmlRegisterType<QQuickImage, 3>(uri, 2, 3,"Image");
-
- qmlRegisterType<QQuickItem, 4>(uri, 2, 4, "Item");
-#if QT_CONFIG(quick_listview)
- qmlRegisterType<QQuickListView, 4>(uri, 2, 4, "ListView");
-#endif
- qmlRegisterType<QQuickMouseArea, 4>(uri, 2, 4, "MouseArea");
-#if QT_CONFIG(quick_shadereffect)
- qmlRegisterType<QQuickShaderEffect, 4>(uri, 2, 4, "ShaderEffect");
-#endif
-
-#if QT_CONFIG(opengl)
- qmlRegisterUncreatableType<QQuickOpenGLInfo>(uri, 2, 4,"OpenGLInfo", QQuickOpenGLInfo::tr("OpenGLInfo is only available via attached properties"));
+#if QT_CONFIG(quick_gridview)
+ qmlRegisterTypesAndRevisions<QQuickGridView>(uri, major);
#endif
- qmlRegisterType<QQuickPinchArea, 5>(uri, 2, 5,"PinchArea");
- qmlRegisterType<QQuickImage, 5>(uri, 2, 5,"Image");
- qmlRegisterType<QQuickMouseArea, 5>(uri, 2, 5, "MouseArea");
- qmlRegisterType<QQuickText, 6>(uri, 2, 6, "Text");
- qmlRegisterType<QQuickTextEdit, 6>(uri, 2, 6, "TextEdit");
- qmlRegisterType<QQuickTextInput, 6>(uri, 2, 6, "TextInput");
-#if QT_CONFIG(quick_positioners)
- qmlRegisterUncreatableType<QQuickBasePositioner, 6>(uri, 2, 6, "Positioner",
- QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
- qmlRegisterType<QQuickColumn, 6>(uri, 2, 6, "Column");
- qmlRegisterType<QQuickRow, 6>(uri, 2, 6, "Row");
- qmlRegisterType<QQuickGrid, 6>(uri, 2, 6, "Grid");
- qmlRegisterType<QQuickFlow, 6>(uri, 2, 6, "Flow");
-#endif
- qmlRegisterUncreatableType<QQuickEnterKeyAttached, 6>(uri, 2, 6, "EnterKey",
- QQuickEnterKeyAttached::tr("EnterKey is only available via attached properties"));
-#if QT_CONFIG(quick_shadereffect)
- qmlRegisterType<QQuickShaderEffectSource, 6>(uri, 2, 6, "ShaderEffectSource");
+#if QT_CONFIG(quick_itemview)
+ qmlRegisterTypesAndRevisions<QQuickItemView>(uri, major);
#endif
- qmlRegisterType<QQuickItem, 7>(uri, 2, 7, "Item");
#if QT_CONFIG(quick_listview)
- qmlRegisterType<QQuickListView, 7>(uri, 2, 7, "ListView");
-#endif
-#if QT_CONFIG(quick_gridview)
- qmlRegisterType<QQuickGridView, 7>(uri, 2, 7, "GridView");
-#endif
- qmlRegisterType<QQuickTextInput, 7>(uri, 2, 7, "TextInput");
- qmlRegisterType<QQuickTextEdit, 7>(uri, 2, 7, "TextEdit");
-#if QT_CONFIG(quick_pathview)
- qmlRegisterType<QQuickPathView, 7>(uri, 2, 7, "PathView");
-#endif
-#if QT_CONFIG(quick_itemview)
- qmlRegisterUncreatableType<QQuickItemView, 7>(uri, 2, 7, itemViewName, itemViewMessage);
+ qmlRegisterTypesAndRevisions<
+ QQuickViewSection,
+ QQuickListView
+ >(uri, major);
#endif
- qmlRegisterUncreatableType<QQuickMouseEvent, 7>(uri, 2, 7, nullptr, QQuickMouseEvent::tr("MouseEvent is only available within handlers in MouseArea"));
-
- qmlRegisterUncreatableType<QQuickGraphicsInfo>(uri, 2, 8,"GraphicsInfo", QQuickGraphicsInfo::tr("GraphicsInfo is only available via attached properties"));
-#if QT_CONFIG(quick_shadereffect)
- qmlRegisterType<QQuickBorderImageMesh>("QtQuick", 2, 8, "BorderImageMesh");
+#if QT_CONFIG(quick_path)
+ qmlRegisterTypesAndRevisions<
+ QQuickCurve,
+ QQuickPath,
+ QQuickPathAngleArc,
+ QQuickPathAnimation,
+ QQuickPathArc,
+ QQuickPathAttribute,
+ QQuickPathCatmullRomCurve,
+ QQuickPathCubic,
+ QQuickPathElement,
+ QQuickPathInterpolator,
+ QQuickPathLine,
+ QQuickPathMove,
+ QQuickPathMultiline,
+ QQuickPathPercent,
+ QQuickPathPolyline,
+ QQuickPathQuad,
+ QQuickPathSvg
+ >(uri, major);
#endif
- qmlRegisterType<QQuickFlickable, 9>(uri, 2, 9, "Flickable");
- qmlRegisterType<QQuickMouseArea, 9>(uri, 2, 9, "MouseArea");
-
-#if QT_CONFIG(quick_path)
- qmlRegisterType<QQuickPathArc, 9>(uri, 2, 9, "PathArc");
- qmlRegisterType<QQuickPathMove>(uri, 2, 9, "PathMove");
+#if QT_CONFIG(quick_pathview)
+ qmlRegisterTypesAndRevisions<QQuickPathView>(uri, major);
#endif
- qmlRegisterType<QQuickText, 9>(uri, 2, 9, "Text");
- qmlRegisterType<QQuickTextInput, 9>(uri, 2, 9, "TextInput");
- qmlRegisterType<QQuickTouchPoint>(uri, 2, 9, "TouchPoint");
- qRegisterMetaType<QPointingDeviceUniqueId>("QPointingDeviceUniqueId");
- qmlRegisterUncreatableType<QPointingDeviceUniqueId>(uri, 2, 9, "PointingDeviceUniqueId", QQuickTouchPoint::tr("PointingDeviceUniqueId is only available via read-only properties"));
-#if QT_CONFIG(quick_positioners)
- qmlRegisterUncreatableType<QQuickBasePositioner, 9>(uri, 2, 9, "Positioner",
- QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
+#if QT_CONFIG(quick_repeater)
+ qmlRegisterTypesAndRevisions<QQuickRepeater>(uri, major);
#endif
#if QT_CONFIG(quick_shadereffect)
- qmlRegisterType<QQuickShaderEffectSource, 9>(uri, 2, 9, "ShaderEffectSource");
+ qmlRegisterTypesAndRevisions<
+ QQuickBorderImageMesh,
+ QQuickGridMesh,
+ QQuickItemLayer,
+ QQuickShaderEffect,
+ QQuickShaderEffectMesh,
+ QQuickShaderEffectSource
+ >(uri, major);
#endif
- qmlRegisterType<QQuickFlickable, 10>(uri, 2, 10, "Flickable");
- qmlRegisterType<QQuickTextEdit, 10>(uri, 2, 10, "TextEdit");
- qmlRegisterType<QQuickText, 10>(uri, 2, 10, "Text");
-
-#if QT_CONFIG(quick_path)
- qmlRegisterType<QQuickPathAngleArc>(uri, 2, 11, "PathAngleArc");
+#if QT_CONFIG(quick_sprite)
+ qmlRegisterTypesAndRevisions<
+ QQuickAnimatedSprite,
+ QQuickSprite,
+ QQuickSpriteSequence
+ >(uri, major);
#endif
-#if QT_CONFIG(quick_animatedimage)
- qmlRegisterType<QQuickAnimatedImage, 11>(uri, 2, 11,"AnimatedImage");
-#endif
- qmlRegisterType<QQuickItem, 11>(uri, 2, 11,"Item");
- qmlRegisterType<QQuickFlickable, 12>(uri, 2, 12, "Flickable");
-
- // classes related to Input Handlers which are newly exposed since 5.12
- qmlRegisterUncreatableType<QQuickPointerEvent>(uri, 2, 12, "PointerEvent",
- QQuickPointerHandler::tr("PointerEvent is only available as a parameter of several signals in PointerHandler"));
- qmlRegisterUncreatableType<QQuickPointerMouseEvent>(uri, 2, 12, "PointerMouseEvent",
- QQuickPointerHandler::tr("PointerMouseEvent is only available as a parameter of several signals in PointerHandler"));
- qmlRegisterUncreatableType<QQuickPointerTouchEvent>(uri, 2, 12, "PointerTouchEvent",
- QQuickPointerHandler::tr("PointerTouchEvent is only available as a parameter of several signals in PointerHandler"));
- qmlRegisterUncreatableType<QQuickEventPoint>(uri, 2, 12, "EventPoint",
- QQuickPointerHandler::tr("EventPoint is only available as a member of PointerEvent"));
- qmlRegisterUncreatableType<QQuickEventTouchPoint>(uri, 2, 12, "EventTouchPoint",
- QQuickPointerHandler::tr("EventTouchPoint is only available as a member of PointerEvent"));
- qmlRegisterUncreatableType<QQuickPointerDevice>(uri, 2, 12, "PointerDevice",
- QQuickPointerHandler::tr("PointerDevice is only available as a property of PointerEvent"));
-
- // Input Handlers are part of QtQuick, not a separate module, since 5.12
- qmlRegisterUncreatableType<QQuickPointerHandler>(uri, 2, 12, "PointerHandler",
- QQuickPointerHandler::tr("PointerHandler is an abstract base class"));
- qmlRegisterType<QQuickPointHandler>(uri, 2, 12, "PointHandler");
- qmlRegisterType<QQuickDragHandler>(uri, 2, 12, "DragHandler");
- qmlRegisterUncreatableType<QQuickDragAxis>(uri, 2, 12, "DragAxis",
- QQuickDragHandler::tr("DragAxis is only available as a grouped property of DragHandler"));
- qmlRegisterType<QQuickHoverHandler>(uri, 2, 12, "HoverHandler");
- qmlRegisterType<QQuickPinchHandler>(uri, 2, 12, "PinchHandler");
- qmlRegisterType<QQuickTapHandler>(uri, 2, 12, "TapHandler");
- qRegisterMetaType<QQuickHandlerPoint>();
-
- // The rest of the 5.12 revisions
- qmlRegisterType<QQuickAnimatedSprite, 12>("QtQuick", 2, 12, "AnimatedSprite");
- qmlRegisterType<QQuickGradient, 12>(uri, 2, 12, "Gradient");
- qmlRegisterType<QQuickFlickable, 12>(uri, 2, 12, "Flickable");
- qmlRegisterType<QQuickText, 12>(uri, 2, 12, "Text");
#if QT_CONFIG(quick_tableview)
- qmlRegisterType<QQuickTableView>(uri, 2, 12, "TableView");
+ qmlRegisterTypesAndRevisions<QQuickTableView>(uri, major);
#endif
-#if QT_CONFIG(quick_itemview)
- qmlRegisterUncreatableType<QQuickItemView, 13>(uri, 2, 13, itemViewName, itemViewMessage);
-#endif
-#if QT_CONFIG(quick_pathview)
- qmlRegisterType<QQuickPathView, 13>(uri, 2, 13, "PathView");
-#endif
-#if QT_CONFIG(quick_gridview)
- qmlRegisterType<QQuickGridView, 13>(uri, 2, 13, "GridView");
-#endif
-#if QT_CONFIG(quick_tableview)
- qmlRegisterType<QQuickTableView, 14>(uri, 2, 14, "TableView");
+#if QT_CONFIG(quick_viewtransitions)
+ qmlRegisterTypesAndRevisions<QQuickViewTransitionAttached>(uri, major);
#endif
+
#if QT_CONFIG(wheelevent)
- qmlRegisterType<QQuickWheelHandler>(uri, 2, 14, "WheelHandler");
+ qmlRegisterTypesAndRevisions<QQuickWheelHandler>(uri, major);
#endif
- qmlRegisterUncreatableType<QQuickImageBase, 14>(uri, 2, 14, "ImageBase",
- QQuickPointerHandler::tr("ImageBase is an abstract base class"));
- qmlRegisterType<QQuickImage, 14>(uri, 2, 14, "Image");
- qmlRegisterType<QQuickDragHandler, 14>(uri, 2, 14, "DragHandler");
}
static void initResources()
@@ -508,12 +398,7 @@ QT_BEGIN_NAMESPACE
void QQuickItemsModule::defineModule()
{
initResources();
-
- QByteArray name = "QtQuick";
- int majorVersion = 2;
- int minorVersion = 0;
-
- qt_quickitems_defineModule(name, majorVersion, minorVersion);
+ qt_quickitems_defineModule();
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitemsmodule_p.h b/src/quick/items/qquickitemsmodule_p.h
index cd79efe256..6ceb0d56e6 100644
--- a/src/quick/items/qquickitemsmodule_p.h
+++ b/src/quick/items/qquickitemsmodule_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <QtGui/qevent.h>
#include <qqml.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +62,15 @@ public:
static void defineModule();
};
+struct QPointingDeviceUniqueIdForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QPointingDeviceUniqueId)
+ QML_NAMED_ELEMENT(PointingDeviceUniqueId)
+ QML_ADDED_IN_MINOR_VERSION(9)
+ QML_UNCREATABLE("PointingDeviceUniqueId is only available via read-only properties.")
+};
+
QT_END_NAMESPACE
#endif // QQUICKITEMSMODULE_P_H
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index bbfbf6244c..fccd467274 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -247,6 +247,8 @@ void QQuickItemView::setModel(const QVariant &m)
connect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
this, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
+ QObjectPrivate::connect(dataModel, &QQmlDelegateModel::delegateChanged, d, &QQuickItemViewPrivate::applyDelegateChange);
emit countChanged();
}
emit modelChanged();
@@ -277,22 +279,8 @@ void QQuickItemView::setDelegate(QQmlComponent *delegate)
if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) {
int oldCount = dataModel->count();
dataModel->setDelegate(delegate);
- if (isComponentComplete()) {
- d->releaseVisibleItems();
- d->releaseItem(d->currentItem);
- d->currentItem = nullptr;
- d->updateSectionCriteria();
- d->refill();
- d->moveReason = QQuickItemViewPrivate::SetIndex;
- d->updateCurrent(d->currentIndex);
- if (d->highlight && d->currentItem) {
- if (d->autoHighlight)
- d->resetHighlightPosition();
- d->updateTrackedItem();
- }
- d->moveReason = QQuickItemViewPrivate::Other;
- d->updateViewport();
- }
+ if (isComponentComplete())
+ d->applyDelegateChange();
if (oldCount != dataModel->count())
emit countChanged();
}
@@ -599,6 +587,7 @@ void QQuickItemView::setHighlightRangeMode(HighlightRangeMode mode)
d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
if (isComponentComplete()) {
d->updateViewport();
+ d->moveReason = QQuickItemViewPrivate::Other;
d->fixupPosition();
}
emit highlightRangeModeChanged();
@@ -621,8 +610,10 @@ void QQuickItemView::setPreferredHighlightBegin(qreal start)
d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
if (isComponentComplete()) {
d->updateViewport();
- if (!isMoving() && !isFlicking())
+ if (!isMoving() && !isFlicking()) {
+ d->moveReason = QQuickItemViewPrivate::Other;
d->fixupPosition();
+ }
}
emit preferredHighlightBeginChanged();
}
@@ -636,8 +627,10 @@ void QQuickItemView::resetPreferredHighlightBegin()
d->highlightRangeStart = 0;
if (isComponentComplete()) {
d->updateViewport();
- if (!isMoving() && !isFlicking())
+ if (!isMoving() && !isFlicking()) {
+ d->moveReason = QQuickItemViewPrivate::Other;
d->fixupPosition();
+ }
}
emit preferredHighlightBeginChanged();
}
@@ -658,8 +651,10 @@ void QQuickItemView::setPreferredHighlightEnd(qreal end)
d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
if (isComponentComplete()) {
d->updateViewport();
- if (!isMoving() && !isFlicking())
+ if (!isMoving() && !isFlicking()) {
+ d->moveReason = QQuickItemViewPrivate::Other;
d->fixupPosition();
+ }
}
emit preferredHighlightEndChanged();
}
@@ -673,8 +668,10 @@ void QQuickItemView::resetPreferredHighlightEnd()
d->highlightRangeEnd = 0;
if (isComponentComplete()) {
d->updateViewport();
- if (!isMoving() && !isFlicking())
+ if (!isMoving() && !isFlicking()) {
+ d->moveReason = QQuickItemViewPrivate::Other;
d->fixupPosition();
+ }
}
emit preferredHighlightEndChanged();
}
@@ -1089,6 +1086,24 @@ qreal QQuickItemViewPrivate::calculatedMaxExtent() const
return maxExtent;
}
+void QQuickItemViewPrivate::applyDelegateChange()
+{
+ releaseVisibleItems();
+ releaseItem(currentItem);
+ currentItem = nullptr;
+ updateSectionCriteria();
+ refill();
+ moveReason = QQuickItemViewPrivate::SetIndex;
+ updateCurrent(currentIndex);
+ if (highlight && currentItem) {
+ if (autoHighlight)
+ resetHighlightPosition();
+ updateTrackedItem();
+ }
+ moveReason = QQuickItemViewPrivate::Other;
+ updateViewport();
+}
+
// for debugging only
void QQuickItemViewPrivate::checkVisible() const
{
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index 66e09f9ed1..6bc00411f0 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -110,6 +110,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickItemView : public QQuickFlickable
Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+ QML_NAMED_ELEMENT(ItemView)
+ QML_UNCREATABLE("ItemView is an abstract base class.")
+ QML_ADDED_IN_MINOR_VERSION(1)
+
public:
// this holds all layout enum values so they can be referred to by other enums
// to ensure consistent values - e.g. QML references to GridView.TopToBottom flow
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index ef674f0fc7..860cf5fa20 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -191,6 +191,8 @@ public:
qreal calculatedMinExtent() const;
qreal calculatedMaxExtent() const;
+ void applyDelegateChange();
+
void applyPendingChanges();
bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult);
bool applyRemovalChange(const QQmlChangeSet::Change &removal, ChangeResult *changeResult, int *removedCount);
diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h
index 0c7a9cad75..5f4e74171e 100644
--- a/src/quick/items/qquickitemviewtransition_p.h
+++ b/src/quick/items/qquickitemviewtransition_p.h
@@ -194,6 +194,10 @@ class QQuickViewTransitionAttached : public QObject
Q_PROPERTY(QList<int> targetIndexes READ targetIndexes NOTIFY targetIndexesChanged)
Q_PROPERTY(QQmlListProperty<QObject> targetItems READ targetItems NOTIFY targetItemsChanged)
+ QML_NAMED_ELEMENT(ViewTransition)
+ QML_UNCREATABLE("ViewTransition is only available via attached properties.")
+ QML_ATTACHED(QQuickViewTransitionAttached)
+
public:
QQuickViewTransitionAttached(QObject *parent);
@@ -227,6 +231,5 @@ private:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickViewTransitionAttached)
-QML_DECLARE_TYPEINFO(QQuickViewTransitionAttached, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKITEMVIEWTRANSITION_P_P_H
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 146917c679..725d35f325 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -49,6 +49,7 @@
#include <QtCore/qmath.h>
#include <private/qquicksmoothedanimation_p_p.h>
+#include <private/qqmlcomponent_p.h>
#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
@@ -190,6 +191,8 @@ public:
}
friend class QQuickViewSection;
+
+ static void setSectionHelper(QQmlContext *context, QQuickItem *sectionItem, const QString &section);
};
//----------------------------------------------------------------------------
@@ -992,14 +995,20 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString &section)
sectionCache[i] = nullptr;
sectionItem->setVisible(true);
QQmlContext *context = QQmlEngine::contextForObject(sectionItem)->parentContext();
- context->setContextProperty(QLatin1String("section"), section);
+ setSectionHelper(context, sectionItem, section);
} else {
QQmlContext *creationContext = sectionCriteria->delegate()->creationContext();
QQmlContext *context = new QQmlContext(
creationContext ? creationContext : qmlContext(q));
- context->setContextProperty(QLatin1String("section"), section);
- QObject *nobj = sectionCriteria->delegate()->beginCreate(context);
+ QQmlComponent* delegate = sectionCriteria->delegate();
+ QQmlComponentPrivate* delegatePriv = QQmlComponentPrivate::get(delegate);
+ QObject *nobj = delegate->beginCreate(context);
if (nobj) {
+ if (delegatePriv->hadRequiredProperties()) {
+ delegate->setInitialProperties(nobj, {{"section", section}});
+ } else {
+ context->setContextProperty(QLatin1String("section"), section);
+ }
QQml_setParent_noEvent(context, nobj);
sectionItem = qobject_cast<QQuickItem *>(nobj);
if (!sectionItem) {
@@ -1069,7 +1078,7 @@ void QQuickListViewPrivate::updateInlineSection(FxListItemSG *listItem)
listItem->setPosition(pos);
} else {
QQmlContext *context = QQmlEngine::contextForObject(listItem->section())->parentContext();
- context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
+ setSectionHelper(context, listItem->section(), listItem->attached->m_section);
}
} else if (listItem->section()) {
qreal pos = listItem->position();
@@ -1125,7 +1134,7 @@ void QQuickListViewPrivate::updateStickySections()
currentSectionItem = getSectionItem(currentSection);
} else if (QString::compare(currentStickySection, currentSection, Qt::CaseInsensitive)) {
QQmlContext *context = QQmlEngine::contextForObject(currentSectionItem)->parentContext();
- context->setContextProperty(QLatin1String("section"), currentSection);
+ setSectionHelper(context, currentSectionItem, currentSection);
}
currentStickySection = currentSection;
if (!currentSectionItem)
@@ -1159,7 +1168,7 @@ void QQuickListViewPrivate::updateStickySections()
nextSectionItem = getSectionItem(nextSection);
} else if (QString::compare(nextStickySection, nextSection, Qt::CaseInsensitive)) {
QQmlContext *context = QQmlEngine::contextForObject(nextSectionItem)->parentContext();
- context->setContextProperty(QLatin1String("section"), nextSection);
+ setSectionHelper(context, nextSectionItem, nextSection);
}
nextStickySection = nextSection;
if (!nextSectionItem)
@@ -1754,6 +1763,14 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
}
}
+void QQuickListViewPrivate::setSectionHelper(QQmlContext *context, QQuickItem *sectionItem, const QString &section)
+{
+ if (context->contextProperty(QLatin1String("section")).isValid())
+ context->setContextProperty(QLatin1String("section"), section);
+ else
+ sectionItem->setProperty("section", section);
+}
+
//----------------------------------------------------------------------------
/*!
@@ -2727,7 +2744,7 @@ void QQuickListView::setFooterPositioning(QQuickListView::FooterPositioning posi
\list
\li The view is first created
- \li The view's \l model changes
+ \li The view's \l model changes in such a way that the visible delegates are completely replaced
\li The view's \l model is \l {QAbstractItemModel::reset()}{reset}, if the model is a QAbstractItemModel subclass
\endlist
@@ -2745,6 +2762,27 @@ void QQuickListView::setFooterPositioning(QQuickListView::FooterPositioning posi
When the view is initialized, the view will create all the necessary items for the view,
then animate them to their correct positions within the view over one second.
+ However when scrolling the view later, the populate transition does not
+ run, even though delegates are being instantiated as they become visible.
+ When the model changes in a way that new delegates become visible, the
+ \l add transition is the one that runs. So you should not depend on the
+ \c populate transition to initialize properties in the delegate, because it
+ does not apply to every delegate. If your animation sets the \c to value of
+ a property, the property should initially have the \c to value, and the
+ animation should set the \c from value in case it is animated:
+
+ \code
+ ListView {
+ ...
+ delegate: Rectangle {
+ opacity: 1 // not necessary because it's the default
+ }
+ populate: Transition {
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 1000 }
+ }
+ }
+ \endcode
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h
index f2bab9e018..1c72a10190 100644
--- a/src/quick/items/qquicklistview_p.h
+++ b/src/quick/items/qquicklistview_p.h
@@ -70,6 +70,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickViewSection : public QObject
Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY criteriaChanged)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int labelPositioning READ labelPositioning WRITE setLabelPositioning NOTIFY labelPositioningChanged)
+ QML_NAMED_ELEMENT(ViewSection)
public:
QQuickViewSection(QQuickListView *parent=nullptr);
@@ -130,6 +131,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickListView : public QQuickItemView
Q_PROPERTY(FooterPositioning footerPositioning READ footerPositioning WRITE setFooterPositioning NOTIFY footerPositioningChanged REVISION 4)
Q_CLASSINFO("DefaultProperty", "data")
+ QML_NAMED_ELEMENT(ListView)
+ QML_ATTACHED(QQuickListViewAttached)
public:
QQuickListView(QQuickItem *parent=nullptr);
@@ -216,7 +219,6 @@ public:
QT_END_NAMESPACE
-QML_DECLARE_TYPEINFO(QQuickListView, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickListView)
QML_DECLARE_TYPE(QQuickViewSection)
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index d0e29c204e..819a3a73e3 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -45,6 +45,7 @@
#include <private/qqmlglobal_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmlincubator_p.h>
QT_BEGIN_NAMESPACE
@@ -664,7 +665,8 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
QV4::Scope scope(v4);
QV4::ScopedValue ipv(scope, initialPropertyValues.value());
QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value());
- d->initializeObjectWithInitialProperties(qmlContext, ipv, obj);
+ auto incubatorPriv = QQmlIncubatorPrivate::get(incubator);
+ d->initializeObjectWithInitialProperties(qmlContext, ipv, obj, incubatorPriv->requiredProperties());
}
void QQuickLoaderIncubator::statusChanged(Status status)
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
index de1dfa9da5..2d560fb856 100644
--- a/src/quick/items/qquickloader_p.h
+++ b/src/quick/items/qquickloader_p.h
@@ -67,6 +67,7 @@ class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
+ QML_NAMED_ELEMENT(Loader)
public:
QQuickLoader(QQuickItem *parent = nullptr);
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index a8f09dc8be..ddf34798d7 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -431,7 +431,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
This signal is emitted in response to both mouse wheel and trackpad scroll gestures.
- The \l {WheelEvent}{wheel} parameter provides information about the event, including the x and y
+ The \a wheel parameter provides information about the event, including the x and y
position, any buttons currently pressed, and information about the wheel movement, including
angleDelta and pixelDelta.
@@ -1069,7 +1069,7 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
Q_D(QQuickMouseArea);
switch (change) {
case ItemVisibleHasChanged:
- if (acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse())) {
+ if (d->effectiveEnable && d->enabled && acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse())) {
if (!d->hovered) {
QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
d->lastScenePos = d->window->mapFromGlobal(cursorPos.toPoint());
diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h
index 0e01fa7915..3d4d113215 100644
--- a/src/quick/items/qquickmousearea_p.h
+++ b/src/quick/items/qquickmousearea_p.h
@@ -85,6 +85,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem
#endif
Q_PROPERTY(bool containsPress READ containsPress NOTIFY containsPressChanged REVISION 4)
Q_PROPERTY(int pressAndHoldInterval READ pressAndHoldInterval WRITE setPressAndHoldInterval NOTIFY pressAndHoldIntervalChanged RESET resetPressAndHoldInterval REVISION 9)
+ QML_NAMED_ELEMENT(MouseArea)
public:
QQuickMouseArea(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index 3eca535a67..b02e58fae4 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -40,6 +40,7 @@
#include "qquickmultipointtoucharea_p.h"
#include <QtQuick/qquickwindow.h>
#include <private/qsgadaptationlayer_p.h>
+#include <private/qevent_p.h>
#include <private/qquickitem_p.h>
#include <private/qguiapplication_p.h>
#include <QEvent>
@@ -410,7 +411,7 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
area should grab the current touch points. By default they will not be grabbed; to grab them call \c gesture.grab(). If the
gesture is not grabbed, the nesting Flickable, for example, would also have an opportunity to grab.
- The gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
+ The \a gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
The corresponding handler is \c onGestureStarted.
*/
@@ -655,7 +656,8 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
// (we may have just obtained enough points to start tracking them -- in that case moved or stationary count as newly pressed)
addTouchPoint(&p);
started = true;
- } else if (touchPointState & Qt::TouchPointMoved) {
+ } else if ((touchPointState & Qt::TouchPointMoved) || p.d->stationaryWithModifiedProperty) {
+ // React to a stationary point with a property change (velocity, pressure) as if the point moved. (QTBUG-77142)
QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
Q_ASSERT(dtp);
_movedTouchPoints.append(dtp);
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index 634ea1c2e2..7506be10a1 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -83,6 +83,7 @@ class Q_AUTOTEST_EXPORT QQuickTouchPoint : public QObject
Q_PROPERTY(qreal previousY READ previousY NOTIFY previousYChanged)
Q_PROPERTY(qreal sceneX READ sceneX NOTIFY sceneXChanged)
Q_PROPERTY(qreal sceneY READ sceneY NOTIFY sceneYChanged)
+ QML_NAMED_ELEMENT(TouchPoint)
public:
QQuickTouchPoint(bool qmlDefined = true)
@@ -187,6 +188,9 @@ class QQuickGrabGestureEvent : public QObject
Q_OBJECT
Q_PROPERTY(QQmlListProperty<QObject> touchPoints READ touchPoints CONSTANT)
Q_PROPERTY(qreal dragThreshold READ dragThreshold CONSTANT)
+ QML_NAMED_ELEMENT(GestureEvent)
+ QML_UNCREATABLE("GestureEvent is only available in the context of handling the gestureStarted signal from MultiPointTouchArea.")
+
public:
QQuickGrabGestureEvent() : _dragThreshold(QGuiApplication::styleHints()->startDragDistance()) {}
@@ -213,6 +217,7 @@ class Q_AUTOTEST_EXPORT QQuickMultiPointTouchArea : public QQuickItem
Q_PROPERTY(int minimumTouchPoints READ minimumTouchPoints WRITE setMinimumTouchPoints NOTIFY minimumTouchPointsChanged)
Q_PROPERTY(int maximumTouchPoints READ maximumTouchPoints WRITE setMaximumTouchPoints NOTIFY maximumTouchPointsChanged)
Q_PROPERTY(bool mouseEnabled READ mouseEnabled WRITE setMouseEnabled NOTIFY mouseEnabledChanged)
+ QML_NAMED_ELEMENT(MultiPointTouchArea)
public:
QQuickMultiPointTouchArea(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickopenglinfo_p.h b/src/quick/items/qquickopenglinfo_p.h
index 86683d5348..b733d205e3 100644
--- a/src/quick/items/qquickopenglinfo_p.h
+++ b/src/quick/items/qquickopenglinfo_p.h
@@ -70,6 +70,11 @@ class QQuickOpenGLInfo : public QObject
Q_PROPERTY(ContextProfile profile READ profile NOTIFY profileChanged FINAL)
Q_PROPERTY(RenderableType renderableType READ renderableType NOTIFY renderableTypeChanged FINAL)
+ QML_NAMED_ELEMENT(OpenGLInfo)
+ QML_UNCREATABLE("OpenGLInfo is only available via attached properties.")
+ QML_ADDED_IN_MINOR_VERSION(4)
+ QML_ATTACHED(QQuickOpenGLInfo)
+
public:
QQuickOpenGLInfo(QQuickItem *item = 0);
@@ -116,6 +121,4 @@ private:
QT_END_NAMESPACE
-QML_DECLARE_TYPEINFO(QQuickOpenGLInfo, QML_HAS_ATTACHED_PROPERTIES)
-
#endif // QQUICKOPENGLINFO_P_H
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index 0fd7df8938..e217fdb5d0 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -189,8 +189,8 @@ class MappedSlotObject: public QtPrivate::QSlotObjectBase
public:
typedef std::function<void()> PropChangedFunc;
- explicit MappedSlotObject(PropChangedFunc func)
- : QSlotObjectBase(&impl), _signalIndex(-1), func(func)
+ explicit MappedSlotObject(PropChangedFunc f)
+ : QSlotObjectBase(&impl), _signalIndex(-1), func(std::move(f))
{ ref(); }
void setSignalIndex(int idx) { _signalIndex = idx; }
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index ddc1fd99d9..4821a409be 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -56,6 +56,9 @@ class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem
Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
+ QML_NAMED_ELEMENT(PaintedItem)
+ QML_UNCREATABLE("Cannot create instance of abstract class PaintedItem.")
+
public:
explicit QQuickPaintedItem(QQuickItem *parent = nullptr);
~QQuickPaintedItem() override;
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 4e81573356..6976665134 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** 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.
@@ -60,8 +60,9 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcItemViewDelegateLifecycle)
+Q_LOGGING_CATEGORY(lcPathView, "qt.quick.pathview")
-const qreal MinimumFlickVelocity = 75.0;
+static const qreal MinimumFlickVelocity = 75;
static QQmlOpenMetaObjectType *qPathViewAttachedType = nullptr;
@@ -90,8 +91,8 @@ void QQuickPathViewAttached::setValue(const QByteArray &name, const QVariant &va
}
QQuickPathViewPrivate::QQuickPathViewPrivate()
- : path(nullptr), currentIndex(0), currentItemOffset(0.0), startPc(0)
- , offset(0.0), offsetAdj(0.0), mappedRange(1.0), mappedCache(0.0)
+ : path(nullptr), currentIndex(0), currentItemOffset(0), startPc(0)
+ , offset(0), offsetAdj(0), mappedRange(1), mappedCache(0)
, stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true)
, autoHighlight(true), highlightUp(false), layoutScheduled(false)
, moving(false), flicking(false), dragging(false), inRequest(false), delegateValidated(false)
@@ -117,10 +118,10 @@ void QQuickPathViewPrivate::init()
q->setFlag(QQuickItem::ItemIsFocusScope);
q->setFiltersChildMouseEvents(true);
qmlobject_connect(&tl, QQuickTimeLine, SIGNAL(updated()),
- q, QQuickPathView, SLOT(ticked()))
+ q, QQuickPathView, SLOT(ticked()));
timer.invalidate();
qmlobject_connect(&tl, QQuickTimeLine, SIGNAL(completed()),
- q, QQuickPathView, SLOT(movementEnding()))
+ q, QQuickPathView, SLOT(movementEnding()));
}
QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool async)
@@ -163,7 +164,7 @@ void QQuickPathView::createdItem(int index, QObject *object)
att->setOnPath(false);
}
item->setParentItem(this);
- d->updateItem(item, 1.0);
+ d->updateItem(item, 1);
} else {
d->requestedIndex = -1;
if (!d->inRequest)
@@ -184,13 +185,13 @@ void QQuickPathView::initItem(int index, QObject *object)
if (att) {
att->m_view = this;
qreal percent = d->positionOfIndex(index);
- if (percent < 1.0 && d->path) {
+ if (percent < 1 && d->path) {
const auto attributes = d->path->attributes();
for (const QString &attr : attributes)
att->setValue(attr.toUtf8(), d->path->attributeAt(attr, percent));
item->setZ(d->requestedZ);
}
- att->setOnPath(percent < 1.0);
+ att->setOnPath(percent < 1);
}
}
}
@@ -264,17 +265,17 @@ void QQuickPathViewPrivate::updateMappedRange()
mappedRange = qreal(modelCount)/pathItems;
mappedCache = qreal(cacheSize)/pathItems/2; // Half of cache at each end
} else {
- mappedRange = 1.0;
- mappedCache = 0.0;
+ mappedRange = 1;
+ mappedCache = 0;
}
}
qreal QQuickPathViewPrivate::positionOfIndex(qreal index) const
{
- qreal pos = -1.0;
+ qreal pos = -1;
if (model && index >= 0 && index < modelCount) {
- qreal start = 0.0;
+ qreal start = 0;
if (haveHighlightRange && (highlightRangeMode != QQuickPathView::NoHighlightRange
|| snapMode != QQuickPathView::NoSnap))
start = highlightRangeStart;
@@ -282,10 +283,10 @@ qreal QQuickPathViewPrivate::positionOfIndex(qreal index) const
globalPos = std::fmod(globalPos, qreal(modelCount)) / modelCount;
if (pathItems != -1 && pathItems < modelCount) {
globalPos += start / mappedRange;
- globalPos = std::fmod(globalPos, qreal(1.0));
+ globalPos = std::fmod(globalPos, qreal(1));
pos = globalPos * mappedRange;
} else {
- pos = std::fmod(globalPos + start, qreal(1.0));
+ pos = std::fmod(globalPos + start, qreal(1));
}
}
@@ -296,7 +297,7 @@ qreal QQuickPathViewPrivate::positionOfIndex(qreal index) const
// account the circular space.
bool QQuickPathViewPrivate::isInBound(qreal position, qreal lower, qreal upper) const
{
- if (lower == upper)
+ if (qFuzzyCompare(lower, upper))
return true;
if (lower > upper) {
if (position > upper && position > lower)
@@ -358,7 +359,7 @@ void QQuickPathViewPrivate::updateHighlight()
} else {
qreal target = currentIndex;
- offsetAdj = 0.0;
+ offsetAdj = 0;
tl.reset(moveHighlight);
moveHighlight.setValue(highlightPosition);
@@ -367,14 +368,14 @@ void QQuickPathViewPrivate::updateHighlight()
if (target - highlightPosition > modelCount/2) {
highlightUp = false;
qreal distance = modelCount - target + highlightPosition;
- tl.move(moveHighlight, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * highlightPosition / distance));
+ tl.move(moveHighlight, 0, QEasingCurve(QEasingCurve::InQuad), int(duration * highlightPosition / distance));
tl.set(moveHighlight, modelCount-0.01);
tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * (modelCount-target) / distance));
} else if (target - highlightPosition <= -modelCount/2) {
highlightUp = true;
qreal distance = modelCount - highlightPosition + target;
tl.move(moveHighlight, modelCount-0.01, QEasingCurve(QEasingCurve::InQuad), int(duration * (modelCount-highlightPosition) / distance));
- tl.set(moveHighlight, 0.0);
+ tl.set(moveHighlight, 0);
tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * target / distance));
} else {
highlightUp = highlightPosition - target < 0;
@@ -386,9 +387,9 @@ void QQuickPathViewPrivate::updateHighlight()
void QQuickPathViewPrivate::setHighlightPosition(qreal pos)
{
- if (pos != highlightPosition) {
- qreal start = 0.0;
- qreal end = 1.0;
+ if (!(qFuzzyCompare(pos, highlightPosition))) {
+ qreal start = 0;
+ qreal end = 1;
if (haveHighlightRange && highlightRangeMode != QQuickPathView::NoHighlightRange) {
start = highlightRangeStart;
end = highlightRangeEnd;
@@ -399,7 +400,7 @@ void QQuickPathViewPrivate::setHighlightPosition(qreal pos)
qreal relativeHighlight = std::fmod(pos + offset, range) / range;
if (!highlightUp && relativeHighlight > end / mappedRange) {
- qreal diff = 1.0 - relativeHighlight;
+ qreal diff = 1 - relativeHighlight;
setOffset(offset + diff * range);
} else if (highlightUp && relativeHighlight >= (end - start) / mappedRange) {
qreal diff = relativeHighlight - (end - start) / mappedRange;
@@ -410,7 +411,7 @@ void QQuickPathViewPrivate::setHighlightPosition(qreal pos)
qreal pathPos = positionOfIndex(pos);
updateItem(highlightItem, pathPos);
if (QQuickPathViewAttached *att = attached(highlightItem))
- att->setOnPath(pathPos < 1.0);
+ att->setOnPath(pathPos < 1);
}
}
@@ -435,10 +436,10 @@ void QQuickPathViewPrivate::updateItem(QQuickItem *item, qreal percent)
const auto attributes = path->attributes();
for (const QString &attr : attributes)
att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
- att->setOnPath(percent < 1.0);
+ att->setOnPath(percent < 1);
}
- QQuickItemPrivate::get(item)->setCulled(percent >= 1.0);
- QPointF pf = path->pointAtPercent(qMin(percent, qreal(1.0)));
+ QQuickItemPrivate::get(item)->setCulled(percent >= 1);
+ QPointF pf = path->pointAtPercent(qMin(percent, qreal(1)));
item->setX(pf.x() - item->width()/2);
item->setY(pf.y() - item->height()/2);
}
@@ -668,7 +669,7 @@ void QQuickPathView::setModel(const QVariant &m)
d->currentIndex = 0;
emit currentIndexChanged();
}
- if (d->offset != 0.0) {
+ if (!(qFuzzyIsNull(d->offset))) {
d->offset = 0;
emit offsetChanged();
}
@@ -820,7 +821,7 @@ void QQuickPathView::decrementCurrentIndex()
\qmlproperty real QtQuick::PathView::offset
The offset specifies how far along the path the items are from their initial positions.
- This is a real number that ranges from 0.0 to the count of items in the model.
+ This is a real number that ranges from \c 0 to the count of items in the model.
*/
qreal QQuickPathView::offset() const
{
@@ -839,7 +840,7 @@ void QQuickPathView::setOffset(qreal offset)
void QQuickPathViewPrivate::setOffset(qreal o)
{
Q_Q(QQuickPathView);
- if (offset != o) {
+ if (!qFuzzyCompare(offset, o)) {
if (isValid() && q->isComponentComplete()) {
qreal oldOffset = offset;
offset = std::fmod(o, qreal(modelCount));
@@ -882,7 +883,6 @@ void QQuickPathViewPrivate::setAdjustedOffset(qreal o)
\sa highlightItem, highlightRangeMode
*/
-
QQmlComponent *QQuickPathView::highlight() const
{
Q_D(const QQuickPathView);
@@ -901,25 +901,26 @@ void QQuickPathView::setHighlight(QQmlComponent *highlight)
}
/*!
- \qmlproperty Item QtQuick::PathView::highlightItem
+ \qmlproperty Item QtQuick::PathView::highlightItem
- \c highlightItem holds the highlight item, which was created
- from the \l highlight component.
+ \c highlightItem holds the highlight item, which was created
+ from the \l highlight component.
- \sa highlight
+ \sa highlight
*/
QQuickItem *QQuickPathView::highlightItem() const
{
Q_D(const QQuickPathView);
return d->highlightItem;
}
+
/*!
\qmlproperty real QtQuick::PathView::preferredHighlightBegin
\qmlproperty real QtQuick::PathView::preferredHighlightEnd
\qmlproperty enumeration QtQuick::PathView::highlightRangeMode
These properties set the preferred range of the highlight (current item)
- within the view. The preferred values must be in the range 0.0-1.0.
+ within the view. The preferred values must be in the range from \c 0 to \c 1.
Valid values for \c highlightRangeMode are:
@@ -960,7 +961,7 @@ qreal QQuickPathView::preferredHighlightBegin() const
void QQuickPathView::setPreferredHighlightBegin(qreal start)
{
Q_D(QQuickPathView);
- if (d->highlightRangeStart == start || start < 0 || start > 1.0)
+ if (qFuzzyCompare(d->highlightRangeStart, start) || start < 0 || start > 1)
return;
d->highlightRangeStart = start;
d->haveHighlightRange = d->highlightRangeStart <= d->highlightRangeEnd;
@@ -977,7 +978,7 @@ qreal QQuickPathView::preferredHighlightEnd() const
void QQuickPathView::setPreferredHighlightEnd(qreal end)
{
Q_D(QQuickPathView);
- if (d->highlightRangeEnd == end || end < 0 || end > 1.0)
+ if (qFuzzyCompare(d->highlightRangeEnd, end) || end < 0 || end > 1)
return;
d->highlightRangeEnd = end;
d->haveHighlightRange = d->highlightRangeStart <= d->highlightRangeEnd;
@@ -1048,7 +1049,7 @@ qreal QQuickPathView::dragMargin() const
void QQuickPathView::setDragMargin(qreal dragMargin)
{
Q_D(QQuickPathView);
- if (d->dragMargin == dragMargin)
+ if (qFuzzyCompare(d->dragMargin, dragMargin))
return;
d->dragMargin = dragMargin;
emit dragMarginChanged();
@@ -1069,7 +1070,7 @@ qreal QQuickPathView::flickDeceleration() const
void QQuickPathView::setFlickDeceleration(qreal dec)
{
Q_D(QQuickPathView);
- if (d->deceleration == dec)
+ if (qFuzzyCompare(d->deceleration, dec))
return;
d->deceleration = dec;
emit flickDecelerationChanged();
@@ -1090,7 +1091,7 @@ qreal QQuickPathView::maximumFlickVelocity() const
void QQuickPathView::setMaximumFlickVelocity(qreal vel)
{
Q_D(QQuickPathView);
- if (vel == d->maximumFlickVelocity)
+ if (qFuzzyCompare(vel, d->maximumFlickVelocity))
return;
d->maximumFlickVelocity = vel;
emit maximumFlickVelocityChanged();
@@ -1580,7 +1581,7 @@ QQuickItem *QQuickPathView::itemAtIndex(int index) const
QPointF QQuickPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
{
const auto pathLength = path->path().length();
- qreal samples = qMin(pathLength / 5, qreal(500.0));
+ qreal samples = qMin(pathLength / 5, qreal(500));
qreal res = pathLength / samples;
qreal mindist = 1e10; // big number
@@ -1601,7 +1602,7 @@ QPointF QQuickPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercen
// now refine
qreal approxPc = nearPc;
- for (qreal i = approxPc-1.0; i < approxPc+1.0; i += 1/(2*res)) {
+ for (qreal i = approxPc-1; i < approxPc+1; i += 1/(2*res)) {
QPointF pt = path->pointAtPercent(i/samples);
QPointF diff = pt - point;
qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
@@ -1623,6 +1624,7 @@ void QQuickPathViewPrivate::addVelocitySample(qreal v)
velocityBuffer.append(v);
if (velocityBuffer.count() > QML_FLICK_SAMPLEBUFFER)
velocityBuffer.remove(0);
+ qCDebug(lcPathView) << "instantaneous velocity" << v;
}
qreal QQuickPathViewPrivate::calcVelocity() const
@@ -1635,6 +1637,7 @@ qreal QQuickPathViewPrivate::calcVelocity() const
velocity += v;
}
velocity /= count;
+ qCDebug(lcPathView) << "average velocity" << velocity << "based on" << count << "samples";
}
return velocity;
}
@@ -1642,7 +1645,7 @@ qreal QQuickPathViewPrivate::calcVelocity() const
qint64 QQuickPathViewPrivate::computeCurrentTime(QInputEvent *event) const
{
if (0 != event->timestamp())
- return event->timestamp();
+ return qint64(event->timestamp());
return timer.elapsed();
}
@@ -1669,7 +1672,7 @@ void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event)
if (item->contains(item->mapFromScene(event->windowPos())))
break;
}
- if (idx == items.count() && dragMargin == 0.) // didn't click on an item
+ if (idx == items.count() && qFuzzyIsNull(dragMargin)) // didn't click on an item
return;
startPoint = pointNear(event->localPos(), &startPc);
@@ -1680,11 +1683,12 @@ void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event)
return;
}
-
- if (tl.isActive() && flicking && flickDuration && qreal(tl.time())/flickDuration < 0.8)
+ if (tl.isActive() && flicking && flickDuration && qreal(tl.time()) / flickDuration < 0.8) {
stealMouse = true; // If we've been flicked then steal the click.
- else
+ q->grabMouse(); // grab it right now too, just to be sure (QTBUG-77173)
+ } else {
stealMouse = false;
+ }
q->setKeepMouseGrab(stealMouse);
timer.start();
@@ -1730,7 +1734,7 @@ void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
moveReason = QQuickPathViewPrivate::Mouse;
int count = pathItems == -1 ? modelCount : qMin(pathItems, modelCount);
qreal diff = (newPc - startPc)*count;
- if (diff) {
+ if (!qFuzzyIsNull(diff)) {
q->setOffset(offset + diff);
if (diff > modelCount/2)
@@ -1740,7 +1744,7 @@ void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
qint64 elapsed = currentTimestamp - lastPosTime;
if (elapsed > 0)
- addVelocitySample(diff / (qreal(elapsed) / 1000.));
+ addVelocitySample(diff / (qreal(elapsed) / 1000));
}
if (!moving) {
moving = true;
@@ -1765,7 +1769,7 @@ void QQuickPathView::mouseReleaseEvent(QMouseEvent *event)
}
}
-void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
+void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *event)
{
Q_Q(QQuickPathView);
stealMouse = false;
@@ -1779,6 +1783,12 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
}
qreal velocity = calcVelocity();
+ qint64 elapsed = computeCurrentTime(event) - lastPosTime;
+ // Let the velocity linearly decay such that it becomes 0 if elapsed time > QML_FLICK_VELOCITY_DECAY_TIME
+ // The intention is that if you are flicking at some speed, then stop in one place for some time before releasing,
+ // the previous velocity is lost. (QTBUG-77173, QTBUG-59052)
+ velocity *= qreal(qMax(0LL, QML_FLICK_VELOCITY_DECAY_TIME - elapsed)) / QML_FLICK_VELOCITY_DECAY_TIME;
+ qCDebug(lcPathView) << "after elapsed time" << elapsed << "velocity decayed to" << velocity;
qreal count = pathItems == -1 ? modelCount : qMin(pathItems, modelCount);
const auto averageItemLength = path->path().length() / count;
qreal pixelVelocity = averageItemLength * velocity;
@@ -1796,32 +1806,32 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
|| snapMode != QQuickPathView::NoSnap)) {
if (snapMode == QQuickPathView::SnapOneItem) {
// encourage snapping one item in direction of motion
- if (velocity > 0.)
+ if (velocity > 0)
dist = qRound(0.5 + offset) - offset;
else
dist = qRound(0.5 - offset) + offset;
} else {
// + 0.25 to encourage moving at least one item in the flick direction
- dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0) + 0.25));
+ dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2) + 0.25));
// round to nearest item.
- if (velocity > 0.)
+ if (velocity > 0)
dist = qRound(dist + offset) - offset;
else
dist = qRound(dist - offset) + offset;
}
// Calculate accel required to stop on item boundary
- if (dist <= 0.) {
- dist = 0.;
- accel = 0.;
+ if (dist <= 0) {
+ dist = 0;
+ accel = 0;
} else {
- accel = v2 / (2.0f * qAbs(dist));
+ accel = v2 / (2 * qAbs(dist));
}
} else {
- dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0)));
+ dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2)));
}
- flickDuration = static_cast<int>(1000 * qAbs(velocity) / accel);
- offsetAdj = 0.0;
+ flickDuration = int(1000 * qAbs(velocity) / accel);
+ offsetAdj = 0;
moveOffset.setValue(offset);
tl.accel(moveOffset, velocity, accel, dist);
tl.callback(QQuickTimeLineCallback(&moveOffset, fixOffsetCallback, this));
@@ -1995,7 +2005,7 @@ void QQuickPathView::refill()
else
qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ":" << item;
}
- if (pos < 1.0) {
+ if (pos < 1) {
d->updateItem(item, pos);
if (idx == d->currentIndex) {
currentVisible = true;
@@ -2005,9 +2015,9 @@ void QQuickPathView::refill()
} else {
d->updateItem(item, pos);
if (QQuickPathViewAttached *att = d->attached(item))
- att->setOnPath(pos < 1.0);
- if (!d->isInBound(pos, d->mappedRange - d->mappedCache, 1.0 + d->mappedCache)) {
- qCDebug(lcItemViewDelegateLifecycle) << "release" << idx << "@" << pos << ", !isInBound: lower" << (d->mappedRange - d->mappedCache) << "upper" << (1.0 + d->mappedCache);
+ att->setOnPath(pos < 1);
+ if (!d->isInBound(pos, d->mappedRange - d->mappedCache, 1 + d->mappedCache)) {
+ qCDebug(lcItemViewDelegateLifecycle) << "release" << idx << "@" << pos << ", !isInBound: lower" << (d->mappedRange - d->mappedCache) << "upper" << (1 + d->mappedCache);
d->releaseItem(item);
it = d->items.erase(it);
} else {
@@ -2023,12 +2033,12 @@ void QQuickPathView::refill()
int endIdx = 0;
qreal endPos;
int startIdx = 0;
- qreal startPos = 0.0;
+ qreal startPos = 0;
const bool wasEmpty = d->items.isEmpty();
if (!wasEmpty) {
//Find the beginning and end, items may not be in sorted order
- endPos = -1.0;
- startPos = 2.0;
+ endPos = -1;
+ startPos = 2;
for (QQuickItem * item : qAsConst(d->items)) {
int idx = d->model->indexOf(item, nullptr);
@@ -2057,10 +2067,10 @@ void QQuickPathView::refill()
if (idx >= d->modelCount)
idx = 0;
qreal nextPos = d->positionOfIndex(idx);
- while ((d->isInBound(nextPos, endPos, 1.0 + d->mappedCache) || !d->items.count())
+ while ((d->isInBound(nextPos, endPos, 1 + d->mappedCache) || !d->items.count())
&& d->items.count() < count+d->cacheSize) {
qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
- QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
+ QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1);
if (!item) {
waiting = true;
break;
@@ -2092,7 +2102,7 @@ void QQuickPathView::refill()
while (!waiting && d->isInBound(nextPos, d->mappedRange - d->mappedCache, startPos)
&& d->items.count() < count+d->cacheSize) {
qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
- QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
+ QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1);
if (!item) {
waiting = true;
break;
@@ -2125,9 +2135,9 @@ void QQuickPathView::refill()
QQuickItem *lastItem = d->items.at(0);
while (idx != endIdx) {
nextPos = d->positionOfIndex(idx);
- if (d->isInBound(nextPos, d->mappedRange - d->mappedCache, 1.0 + d->mappedCache)) {
+ if (d->isInBound(nextPos, d->mappedRange - d->mappedCache, 1 + d->mappedCache)) {
//This gets the reference from the delegate model, and will not re-create
- QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
+ QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1);
if (!item) {
waiting = true;
break;
@@ -2161,13 +2171,13 @@ void QQuickPathView::refill()
bool currentChanged = false;
if (!currentVisible) {
- d->currentItemOffset = 1.0;
+ d->currentItemOffset = 1;
if (d->currentItem) {
- d->updateItem(d->currentItem, 1.0);
+ d->updateItem(d->currentItem, 1);
} else if (!waiting && d->currentIndex >= 0 && d->currentIndex < d->modelCount) {
if ((d->currentItem = d->getItem(d->currentIndex, d->currentIndex))) {
currentChanged = true;
- d->updateItem(d->currentItem, 1.0);
+ d->updateItem(d->currentItem, 1);
if (QQuickPathViewAttached *att = d->attached(d->currentItem))
att->setIsCurrentItem(true);
}
@@ -2361,7 +2371,7 @@ void QQuickPathViewPrivate::createCurrentItem()
}
} else if (currentIndex >= 0 && currentIndex < modelCount) {
if ((currentItem = getItem(currentIndex, currentIndex))) {
- updateItem(currentItem, 1.0);
+ updateItem(currentItem, 1);
if (QQuickPathViewAttached *att = attached(currentItem))
att->setIsCurrentItem(true);
}
@@ -2395,7 +2405,7 @@ void QQuickPathViewPrivate::updateCurrent()
void QQuickPathViewPrivate::fixOffsetCallback(void *d)
{
- ((QQuickPathViewPrivate *)d)->fixOffset();
+ static_cast<QQuickPathViewPrivate *>(d)->fixOffset();
}
void QQuickPathViewPrivate::fixOffset()
@@ -2420,7 +2430,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason)
qreal targetOffset = std::fmod(qreal(modelCount - index), qreal(modelCount));
moveReason = reason;
- offsetAdj = 0.0;
+ offsetAdj = 0;
tl.reset(moveOffset);
moveOffset.setValue(offset);
@@ -2432,20 +2442,20 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason)
if (!duration || qAbs(offset - targetOffset) < threshold || (qFuzzyIsNull(targetOffset) && qAbs(modelCount - offset) < threshold)) {
tl.set(moveOffset, targetOffset);
- } else if (moveDirection == QQuickPathView::Positive || (moveDirection == QQuickPathView::Shortest && targetOffset - offset > modelCount/2.0)) {
+ } else if (moveDirection == QQuickPathView::Positive || (moveDirection == QQuickPathView::Shortest && targetOffset - offset > modelCount/2)) {
qreal distance = modelCount - targetOffset + offset;
if (targetOffset > moveOffset) {
- tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance));
+ tl.move(moveOffset, 0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance));
tl.set(moveOffset, modelCount);
- tl.move(moveOffset, targetOffset, QEasingCurve(offset == 0.0 ? QEasingCurve::InOutQuad : QEasingCurve::OutQuad), int(duration * (modelCount-targetOffset) / distance));
+ tl.move(moveOffset, targetOffset, QEasingCurve(qFuzzyIsNull(offset) ? QEasingCurve::InOutQuad : QEasingCurve::OutQuad), int(duration * (modelCount-targetOffset) / distance));
} else {
tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
}
- } else if (moveDirection == QQuickPathView::Negative || targetOffset - offset <= -modelCount/2.0) {
+ } else if (moveDirection == QQuickPathView::Negative || targetOffset - offset <= -modelCount/2) {
qreal distance = modelCount - offset + targetOffset;
if (targetOffset < moveOffset) {
- tl.move(moveOffset, modelCount, QEasingCurve(targetOffset == 0 ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance));
- tl.set(moveOffset, 0.0);
+ tl.move(moveOffset, modelCount, QEasingCurve(qFuzzyIsNull(targetOffset) ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance));
+ tl.set(moveOffset, 0);
tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::OutQuad), int(duration * targetOffset / distance));
} else {
tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
index 66be7fa6ff..c12358e4f6 100644
--- a/src/quick/items/qquickpathview_p.h
+++ b/src/quick/items/qquickpathview_p.h
@@ -100,6 +100,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathView : public QQuickItem
Q_PROPERTY(MovementDirection movementDirection READ movementDirection WRITE setMovementDirection NOTIFY movementDirectionChanged REVISION 7)
Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged)
+ QML_NAMED_ELEMENT(PathView)
+ QML_ATTACHED(QQuickPathViewAttached)
public:
QQuickPathView(QQuickItem *parent = nullptr);
@@ -299,6 +301,5 @@ private:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickPathView)
-QML_DECLARE_TYPEINFO(QQuickPathView, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKPATHVIEW_P_H
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index cf21555823..d7f814cc8a 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -70,6 +70,7 @@ class Q_AUTOTEST_EXPORT QQuickPinch : public QObject
Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+ QML_NAMED_ELEMENT(Pinch)
public:
QQuickPinch();
@@ -210,6 +211,7 @@ class Q_AUTOTEST_EXPORT QQuickPinchEvent : public QObject
Q_PROPERTY(QPointF startPoint2 READ startPoint2)
Q_PROPERTY(int pointCount READ pointCount)
Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
+ QML_ANONYMOUS
public:
QQuickPinchEvent(QPointF c, qreal s, qreal a, qreal r)
@@ -268,6 +270,7 @@ class Q_AUTOTEST_EXPORT QQuickPinchArea : public QQuickItem
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(QQuickPinch *pinch READ pinch CONSTANT)
+ QML_NAMED_ELEMENT(PinchArea)
public:
QQuickPinchArea(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h
index 94a737e1f1..b924cb9c12 100644
--- a/src/quick/items/qquickpositioners_p.h
+++ b/src/quick/items/qquickpositioners_p.h
@@ -112,6 +112,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte
Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6)
Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6)
Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
+
+ QML_NAMED_ELEMENT(Positioner)
+ QML_UNCREATABLE("Positioner is an abstract type that is only available as an attached property.")
+ QML_ATTACHED(QQuickPositionerAttached)
+
public:
enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
@@ -230,6 +235,7 @@ private:
class Q_AUTOTEST_EXPORT QQuickColumn : public QQuickBasePositioner
{
Q_OBJECT
+ QML_NAMED_ELEMENT(Column)
public:
QQuickColumn(QQuickItem *parent=nullptr);
@@ -246,6 +252,8 @@ class Q_AUTOTEST_EXPORT QQuickRow: public QQuickBasePositioner
Q_OBJECT
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+ QML_NAMED_ELEMENT(Row)
+
public:
QQuickRow(QQuickItem *parent=nullptr);
@@ -279,6 +287,7 @@ class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner
Q_PROPERTY(HAlignment horizontalItemAlignment READ hItemAlign WRITE setHItemAlign NOTIFY horizontalAlignmentChanged REVISION 1)
Q_PROPERTY(HAlignment effectiveHorizontalItemAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION 1)
Q_PROPERTY(VAlignment verticalItemAlignment READ vItemAlign WRITE setVItemAlign NOTIFY verticalAlignmentChanged REVISION 1)
+ QML_NAMED_ELEMENT(Grid)
public:
QQuickGrid(QQuickItem *parent=nullptr);
@@ -359,6 +368,7 @@ class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner
Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+ QML_NAMED_ELEMENT(Flow)
public:
QQuickFlow(QQuickItem *parent=nullptr);
@@ -395,6 +405,5 @@ QML_DECLARE_TYPE(QQuickGrid)
QML_DECLARE_TYPE(QQuickFlow)
QML_DECLARE_TYPE(QQuickBasePositioner)
-QML_DECLARE_TYPEINFO(QQuickBasePositioner, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKPOSITIONERS_P_H
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index d56a03d22d..934300b63b 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -66,6 +66,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPen : public QObject
Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY penChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY penChanged)
Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY penChanged)
+ QML_ANONYMOUS
public:
QQuickPen(QObject *parent=nullptr);
@@ -96,6 +97,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGradientStop : public QObject
Q_PROPERTY(qreal position READ position WRITE setPosition)
Q_PROPERTY(QColor color READ color WRITE setColor)
+ QML_NAMED_ELEMENT(GradientStop)
public:
QQuickGradientStop(QObject *parent=nullptr);
@@ -121,6 +123,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGradient : public QObject
Q_PROPERTY(QQmlListProperty<QQuickGradientStop> stops READ stops)
Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged REVISION 12)
Q_CLASSINFO("DefaultProperty", "stops")
+ QML_NAMED_ELEMENT(Gradient)
Q_ENUMS(QGradient::Preset)
public:
@@ -161,6 +164,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem
Q_PROPERTY(QJSValue gradient READ gradient WRITE setGradient RESET resetGradient)
Q_PROPERTY(QQuickPen * border READ border CONSTANT)
Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+ QML_NAMED_ELEMENT(Rectangle)
public:
QQuickRectangle(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 83b3372ed9..9f9777f199 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -188,8 +188,7 @@ void QQuickRenderControlPrivate::windowDestroyed()
if (window) {
rc->invalidate();
- delete QQuickWindowPrivate::get(window)->animationController;
- QQuickWindowPrivate::get(window)->animationController = nullptr;
+ QQuickWindowPrivate::get(window)->animationController.reset();
#if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl)
if (QOpenGLContext::currentContext())
@@ -276,6 +275,7 @@ void QQuickRenderControl::polishItems()
if (!d->window)
return;
cd->polishItems();
+ emit d->window->afterAnimating();
}
/*!
diff --git a/src/quick/items/qquickrepeater_p.h b/src/quick/items/qquickrepeater_p.h
index dbe3cd0c55..20984fa23e 100644
--- a/src/quick/items/qquickrepeater_p.h
+++ b/src/quick/items/qquickrepeater_p.h
@@ -70,6 +70,7 @@ class Q_AUTOTEST_EXPORT QQuickRepeater : public QQuickItem
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_CLASSINFO("DefaultProperty", "delegate")
+ QML_NAMED_ELEMENT(Repeater)
public:
QQuickRepeater(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h
index f5187a8eea..56b0ee86ab 100644
--- a/src/quick/items/qquickscalegrid_p_p.h
+++ b/src/quick/items/qquickscalegrid_p_p.h
@@ -69,6 +69,7 @@ class Q_AUTOTEST_EXPORT QQuickScaleGrid : public QObject
Q_PROPERTY(int top READ top WRITE setTop NOTIFY topBorderChanged)
Q_PROPERTY(int right READ right WRITE setRight NOTIFY rightBorderChanged)
Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomBorderChanged)
+ QML_ANONYMOUS
public:
QQuickScaleGrid(QObject *parent=nullptr);
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index b057fd9d8f..b17e505f4f 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -229,7 +229,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmlattachedmethod int Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
- Returns the rotation angle, in degrees, between the two specified angles.
+ Returns the rotation angle, in degrees, between the specified screen
+ orientations \a a and \a b.
*/
/*!
diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h
index 10e524e4a0..9d9f9a1567 100644
--- a/src/quick/items/qquickscreen_p.h
+++ b/src/quick/items/qquickscreen_p.h
@@ -86,6 +86,10 @@ class Q_AUTOTEST_EXPORT QQuickScreenInfo : public QObject
Q_PROPERTY(int virtualX READ virtualX NOTIFY virtualXChanged REVISION 3)
Q_PROPERTY(int virtualY READ virtualY NOTIFY virtualYChanged REVISION 3)
+ QML_NAMED_ELEMENT(ScreenInfo)
+ QML_ADDED_IN_MINOR_VERSION(3)
+ QML_UNCREATABLE("ScreenInfo can only be used via the attached property.")
+
public:
QQuickScreenInfo(QObject *parent = nullptr, QScreen *wrappedScreen = nullptr);
@@ -161,13 +165,16 @@ private:
class Q_AUTOTEST_EXPORT QQuickScreen : public QObject
{
Q_OBJECT
+ QML_NAMED_ELEMENT(Screen)
+ QML_UNCREATABLE("Screen can only be used via the attached property.")
+ QML_ATTACHED(QQuickScreenAttached)
+
public:
static QQuickScreenAttached *qmlAttachedProperties(QObject *object){ return new QQuickScreenAttached(object); }
};
QT_END_NAMESPACE
-QML_DECLARE_TYPEINFO(QQuickScreen, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickScreenInfo)
#endif
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index 6e2f35882b..c14907092c 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -75,6 +75,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffect : public QQuickItem
Q_PROPERTY(QString log READ log NOTIFY logChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(bool supportsAtlasTextures READ supportsAtlasTextures WRITE setSupportsAtlasTextures NOTIFY supportsAtlasTexturesChanged REVISION 4)
+ QML_NAMED_ELEMENT(ShaderEffect)
public:
enum CullMode {
diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h
index 79e05a5f9f..710d37c275 100644
--- a/src/quick/items/qquickshadereffectmesh_p.h
+++ b/src/quick/items/qquickshadereffectmesh_p.h
@@ -49,6 +49,7 @@ QT_REQUIRE_CONFIG(quick_shadereffect);
#include <QtCore/qsize.h>
#include <QtCore/qvector.h>
#include <QtCore/qbytearray.h>
+#include <QtQml/qqml.h>
#ifndef QQUICKSHADEREFFECTMESH_P_H
#define QQUICKSHADEREFFECTMESH_P_H
@@ -75,6 +76,10 @@ class QRectF;
class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectMesh : public QObject
{
Q_OBJECT
+
+ QML_NAMED_ELEMENT(ShaderEffectMesh)
+ QML_UNCREATABLE("Cannot create instance of abstract class ShaderEffectMesh.")
+
public:
QQuickShaderEffectMesh(QObject *parent = nullptr);
virtual bool validateAttributes(const QVector<QByteArray> &attributes, int *posIndex) = 0;
@@ -96,6 +101,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGridMesh : public QQuickShaderEffectMesh
{
Q_OBJECT
Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
+ QML_NAMED_ELEMENT(GridMesh)
public:
QQuickGridMesh(QObject *parent = nullptr);
bool validateAttributes(const QVector<QByteArray> &attributes, int *posIndex) override;
@@ -123,6 +129,10 @@ class QQuickBorderImageMesh : public QQuickShaderEffectMesh
Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged)
Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
+
+ QML_NAMED_ELEMENT(BorderImageMesh)
+ QML_ADDED_IN_MINOR_VERSION(8)
+
public:
QQuickBorderImageMesh(QObject *parent = nullptr);
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index d612d1179f..c0a1ccab78 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -89,6 +89,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION 6)
Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged REVISION 9)
+ QML_NAMED_ELEMENT(ShaderEffectSource)
public:
enum WrapMode {
diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h
index fab9e75190..98e5b82db8 100644
--- a/src/quick/items/qquicksprite_p.h
+++ b/src/quick/items/qquicksprite_p.h
@@ -86,6 +86,7 @@ class Q_QUICK_EXPORT QQuickSprite : public QQuickStochasticState
Q_PROPERTY(qreal frameRateVariation READ frameRateVariation WRITE setFrameRateVariation NOTIFY frameRateVariationChanged)
Q_PROPERTY(int frameDuration READ frameDuration WRITE setFrameDuration NOTIFY frameDurationChanged RESET resetFrameDuration)
Q_PROPERTY(int frameDurationVariation READ frameDurationVariation WRITE setFrameDurationVariation NOTIFY frameDurationVariationChanged)
+ QML_NAMED_ELEMENT(Sprite)
public:
explicit QQuickSprite(QObject *parent = nullptr);
diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h
index 12c80d6a27..8361f7832a 100644
--- a/src/quick/items/qquickspritesequence_p.h
+++ b/src/quick/items/qquickspritesequence_p.h
@@ -74,6 +74,7 @@ class Q_AUTOTEST_EXPORT QQuickSpriteSequence : public QQuickItem
//###try to share similar spriteEngines for less overhead?
Q_PROPERTY(QQmlListProperty<QQuickSprite> sprites READ sprites)
Q_CLASSINFO("DefaultProperty", "sprites")
+ QML_NAMED_ELEMENT(SpriteSequence)
public:
explicit QQuickSpriteSequence(QQuickItem *parent = nullptr);
diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp
index fe1dfd349e..07767d377d 100644
--- a/src/quick/items/qquickstateoperations.cpp
+++ b/src/quick/items/qquickstateoperations.cpp
@@ -44,6 +44,7 @@
#include <QtQml/qqmlinfo.h>
#include <QtCore/qmath.h>
+#include <memory>
QT_BEGIN_NAMESPACE
@@ -51,15 +52,17 @@ class QQuickParentChangePrivate : public QQuickStateOperationPrivate
{
Q_DECLARE_PUBLIC(QQuickParentChange)
public:
- QQuickParentChangePrivate() : target(nullptr), parent(nullptr), origParent(nullptr), origStackBefore(nullptr),
- rewindParent(nullptr), rewindStackBefore(nullptr) {}
-
- QQuickItem *target;
+ QQuickItem *target = nullptr;
QPointer<QQuickItem> parent;
- QPointer<QQuickItem> origParent;
- QPointer<QQuickItem> origStackBefore;
- QQuickItem *rewindParent;
- QQuickItem *rewindStackBefore;
+
+ struct StateSnapshot {
+ QPointer<QQuickItem> parent;
+ QPointer<QQuickItem> stackBefore;
+ qreal x = 0, y = 0, width = 0, height = 0, scale = 0, rotation = 0;
+ };
+
+ std::unique_ptr<StateSnapshot> orig;
+ std::unique_ptr<StateSnapshot> rewind;
QQmlNullableValue<QQmlScriptString> xString;
QQmlNullableValue<QQmlScriptString> yString;
@@ -68,10 +71,11 @@ public:
QQmlNullableValue<QQmlScriptString> scaleString;
QQmlNullableValue<QQmlScriptString> rotationString;
- void doChange(QQuickItem *targetParent, QQuickItem *stackBefore = nullptr);
+ void doChange(QQuickItem *targetParent);
+ void reverseRewindHelper(const std::unique_ptr<StateSnapshot> &snapshot);
};
-void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *stackBefore)
+void QQuickParentChangePrivate::doChange(QQuickItem *targetParent)
{
if (targetParent && target && target->parentItem()) {
Q_Q(QQuickParentChange);
@@ -137,11 +141,6 @@ void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *s
} else if (target) {
target->setParentItem(targetParent);
}
-
- //restore the original stack position.
- //### if stackBefore has also been reparented this won't work
- if (target && stackBefore)
- target->stackBefore(stackBefore);
}
/*!
@@ -200,7 +199,7 @@ QQmlScriptString QQuickParentChange::x() const
return d->xString.value;
}
-void QQuickParentChange::setX(QQmlScriptString x)
+void QQuickParentChange::setX(const QQmlScriptString &x)
{
Q_D(QQuickParentChange);
d->xString = x;
@@ -218,7 +217,7 @@ QQmlScriptString QQuickParentChange::y() const
return d->yString.value;
}
-void QQuickParentChange::setY(QQmlScriptString y)
+void QQuickParentChange::setY(const QQmlScriptString &y)
{
Q_D(QQuickParentChange);
d->yString = y;
@@ -236,7 +235,7 @@ QQmlScriptString QQuickParentChange::width() const
return d->widthString.value;
}
-void QQuickParentChange::setWidth(QQmlScriptString width)
+void QQuickParentChange::setWidth(const QQmlScriptString &width)
{
Q_D(QQuickParentChange);
d->widthString = width;
@@ -254,7 +253,7 @@ QQmlScriptString QQuickParentChange::height() const
return d->heightString.value;
}
-void QQuickParentChange::setHeight(QQmlScriptString height)
+void QQuickParentChange::setHeight(const QQmlScriptString &height)
{
Q_D(QQuickParentChange);
d->heightString = height;
@@ -272,7 +271,7 @@ QQmlScriptString QQuickParentChange::scale() const
return d->scaleString.value;
}
-void QQuickParentChange::setScale(QQmlScriptString scale)
+void QQuickParentChange::setScale(const QQmlScriptString &scale)
{
Q_D(QQuickParentChange);
d->scaleString = scale;
@@ -290,7 +289,7 @@ QQmlScriptString QQuickParentChange::rotation() const
return d->rotationString.value;
}
-void QQuickParentChange::setRotation(QQmlScriptString rotation)
+void QQuickParentChange::setRotation(const QQmlScriptString &rotation)
{
Q_D(QQuickParentChange);
d->rotationString = rotation;
@@ -305,7 +304,7 @@ bool QQuickParentChange::rotationIsSet() const
QQuickItem *QQuickParentChange::originalParent() const
{
Q_D(const QQuickParentChange);
- return d->origParent;
+ return d->orig ? d->orig->parent : nullptr;
}
/*!
@@ -473,21 +472,11 @@ void QQuickParentChange::saveOriginals()
{
Q_D(QQuickParentChange);
saveCurrentValues();
- d->origParent = d->rewindParent;
- d->origStackBefore = d->rewindStackBefore;
+ if (!d->orig)
+ d->orig.reset(new QQuickParentChangePrivate::StateSnapshot);
+ *d->orig = *d->rewind;
}
-/*void QQuickParentChange::copyOriginals(QQuickStateActionEvent *other)
-{
- Q_D(QQuickParentChange);
- QQuickParentChange *pc = static_cast<QQuickParentChange*>(other);
-
- d->origParent = pc->d_func()->rewindParent;
- d->origStackBefore = pc->d_func()->rewindStackBefore;
-
- saveCurrentValues();
-}*/
-
void QQuickParentChange::execute()
{
Q_D(QQuickParentChange);
@@ -499,10 +488,26 @@ bool QQuickParentChange::isReversable()
return true;
}
+void QQuickParentChangePrivate::reverseRewindHelper(const std::unique_ptr<QQuickParentChangePrivate::StateSnapshot> &snapshot)
+{
+ if (!target || !snapshot)
+ return;
+ target->setX(snapshot->x);
+ target->setY(snapshot->y);
+ target->setScale(snapshot->scale);
+ target->setWidth(snapshot->width);
+ target->setHeight(snapshot->height);
+ target->setRotation(snapshot->rotation);
+ target->setParentItem(snapshot->parent);
+ if (snapshot->stackBefore)
+ target->stackBefore(snapshot->stackBefore);
+}
+
+
void QQuickParentChange::reverse()
{
Q_D(QQuickParentChange);
- d->doChange(d->origParent, d->origStackBefore);
+ d->reverseRewindHelper(d->orig);
}
QQuickStateActionEvent::EventType QQuickParentChange::type() const
@@ -524,21 +529,28 @@ void QQuickParentChange::saveCurrentValues()
{
Q_D(QQuickParentChange);
if (!d->target) {
- d->rewindParent = nullptr;
- d->rewindStackBefore = nullptr;
+ d->rewind = nullptr;
return;
}
- d->rewindParent = d->target->parentItem();
- d->rewindStackBefore = nullptr;
+ d->rewind.reset(new QQuickParentChangePrivate::StateSnapshot);
+ d->rewind->x = d->target->x();
+ d->rewind->y = d->target->y();
+ d->rewind->scale = d->target->scale();
+ d->rewind->width = d->target->width();
+ d->rewind->height = d->target->height();
+ d->rewind->rotation = d->target->rotation();
+
+ d->rewind->parent = d->target->parentItem();
+ d->rewind->stackBefore = nullptr;
- if (!d->rewindParent)
+ if (!d->rewind->parent)
return;
- QList<QQuickItem *> children = d->rewindParent->childItems();
+ QList<QQuickItem *> children = d->rewind->parent->childItems();
for (int ii = 0; ii < children.count() - 1; ++ii) {
if (children.at(ii) == d->target) {
- d->rewindStackBefore = children.at(ii + 1);
+ d->rewind->stackBefore = children.at(ii + 1);
break;
}
}
@@ -547,7 +559,8 @@ void QQuickParentChange::saveCurrentValues()
void QQuickParentChange::rewind()
{
Q_D(QQuickParentChange);
- d->doChange(d->rewindParent, d->rewindStackBefore);
+ d->reverseRewindHelper(d->rewind);
+ d->rewind.reset();
}
/*!
diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h
index e947b2213f..d451dc6f77 100644
--- a/src/quick/items/qquickstateoperations_p.h
+++ b/src/quick/items/qquickstateoperations_p.h
@@ -74,6 +74,7 @@ class Q_AUTOTEST_EXPORT QQuickParentChange : public QQuickStateOperation, public
Q_PROPERTY(QQmlScriptString height READ height WRITE setHeight)
Q_PROPERTY(QQmlScriptString scale READ scale WRITE setScale)
Q_PROPERTY(QQmlScriptString rotation READ rotation WRITE setRotation)
+ QML_NAMED_ELEMENT(ParentChange)
public:
QQuickParentChange(QObject *parent=nullptr);
~QQuickParentChange();
@@ -87,27 +88,27 @@ public:
QQuickItem *originalParent() const;
QQmlScriptString x() const;
- void setX(QQmlScriptString x);
+ void setX(const QQmlScriptString &x);
bool xIsSet() const;
QQmlScriptString y() const;
- void setY(QQmlScriptString y);
+ void setY(const QQmlScriptString &y);
bool yIsSet() const;
QQmlScriptString width() const;
- void setWidth(QQmlScriptString width);
+ void setWidth(const QQmlScriptString &width);
bool widthIsSet() const;
QQmlScriptString height() const;
- void setHeight(QQmlScriptString height);
+ void setHeight(const QQmlScriptString &height);
bool heightIsSet() const;
QQmlScriptString scale() const;
- void setScale(QQmlScriptString scale);
+ void setScale(const QQmlScriptString &scale);
bool scaleIsSet() const;
QQmlScriptString rotation() const;
- void setRotation(QQmlScriptString rotation);
+ void setRotation(const QQmlScriptString &rotation);
bool rotationIsSet() const;
ActionList actions() override;
@@ -136,6 +137,7 @@ class Q_AUTOTEST_EXPORT QQuickAnchorSet : public QObject
Q_PROPERTY(QQmlScriptString bottom READ bottom WRITE setBottom RESET resetBottom)
Q_PROPERTY(QQmlScriptString verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter)
Q_PROPERTY(QQmlScriptString baseline READ baseline WRITE setBaseline RESET resetBaseline)
+ QML_ANONYMOUS
public:
QQuickAnchorSet(QObject *parent=nullptr);
@@ -185,6 +187,7 @@ class Q_AUTOTEST_EXPORT QQuickAnchorChanges : public QQuickStateOperation, publi
Q_PROPERTY(QQuickItem *target READ object WRITE setObject)
Q_PROPERTY(QQuickAnchorSet *anchors READ anchors CONSTANT)
+ QML_NAMED_ELEMENT(AnchorChanges)
public:
QQuickAnchorChanges(QObject *parent=nullptr);
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 75e0a1018f..295c6898bc 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -54,6 +54,7 @@
/*!
\qmltype TableView
\inqmlmodule QtQuick
+ \since 5.12
\ingroup qtquick-views
\inherits Flickable
\brief Provides a table view of items to display data from a model.
@@ -1823,18 +1824,9 @@ void QQuickTableViewPrivate::beginRebuildTable()
void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
{
- if (rebuildOptions.testFlag(RebuildOption::LayoutOnly)
- || rowHeightProvider.isUndefined() || columnWidthProvider.isUndefined()) {
- // Since we don't have both size providers, we need to calculate the
- // size of each row and column based on the size of the delegate items.
- // This couldn't be done while we were loading the initial rows and
- // columns, since during the process, we didn't have all the items
- // available yet for the calculation. So we do it now. The exception
- // is if we specifically only requested a relayout.
- clearEdgeSizeCache();
- relayoutTableItems();
- syncLoadedTableRectFromLoadedTable();
- }
+ clearEdgeSizeCache();
+ relayoutTableItems();
+ syncLoadedTableRectFromLoadedTable();
if (syncView || rebuildOptions.testFlag(RebuildOption::All)) {
// We try to limit how often we update the content size. The main reason is that is has a
@@ -2590,7 +2582,7 @@ QJSValue QQuickTableView::rowHeightProvider() const
return d_func()->rowHeightProvider;
}
-void QQuickTableView::setRowHeightProvider(QJSValue provider)
+void QQuickTableView::setRowHeightProvider(const QJSValue &provider)
{
Q_D(QQuickTableView);
if (provider.strictlyEquals(d->rowHeightProvider))
@@ -2606,7 +2598,7 @@ QJSValue QQuickTableView::columnWidthProvider() const
return d_func()->columnWidthProvider;
}
-void QQuickTableView::setColumnWidthProvider(QJSValue provider)
+void QQuickTableView::setColumnWidthProvider(const QJSValue &provider)
{
Q_D(QQuickTableView);
if (provider.strictlyEquals(d->columnWidthProvider))
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
index 3b113efa4f..5ef73a816f 100644
--- a/src/quick/items/qquicktableview_p.h
+++ b/src/quick/items/qquicktableview_p.h
@@ -82,6 +82,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTableView : public QQuickFlickable
Q_PROPERTY(QQuickTableView *syncView READ syncView WRITE setSyncView NOTIFY syncViewChanged REVISION 14)
Q_PROPERTY(Qt::Orientations syncDirection READ syncDirection WRITE setSyncDirection NOTIFY syncDirectionChanged REVISION 14)
+ QML_NAMED_ELEMENT(TableView)
+ QML_ADDED_IN_MINOR_VERSION(12)
+ QML_ATTACHED(QQuickTableViewAttached)
+
public:
QQuickTableView(QQuickItem *parent = nullptr);
~QQuickTableView() override;
@@ -95,10 +99,10 @@ public:
void setColumnSpacing(qreal spacing);
QJSValue rowHeightProvider() const;
- void setRowHeightProvider(QJSValue provider);
+ void setRowHeightProvider(const QJSValue &provider);
QJSValue columnWidthProvider() const;
- void setColumnWidthProvider(QJSValue provider);
+ void setColumnWidthProvider(const QJSValue &provider);
virtual QVariant model() const;
virtual void setModel(const QVariant &newModel);
@@ -186,6 +190,5 @@ private:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickTableView)
-QML_DECLARE_TYPEINFO(QQuickTableView, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKTABLEVIEW_P_H
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index 45f387cb12..394ea25b83 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -100,6 +100,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
Q_PROPERTY(QJSValue fontInfo READ fontInfo NOTIFY fontInfoChanged REVISION 9)
Q_PROPERTY(QSizeF advance READ advance NOTIFY contentSizeChanged REVISION 10)
+ QML_NAMED_ELEMENT(Text)
public:
QQuickText(QQuickItem *parent=nullptr);
@@ -329,6 +330,7 @@ class QQuickTextLine : public QObject
Q_PROPERTY(qreal height READ height WRITE setHeight)
Q_PROPERTY(qreal x READ x WRITE setX)
Q_PROPERTY(qreal y READ y WRITE setY)
+ QML_ANONYMOUS
public:
QQuickTextLine();
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 5c4ecd60aa..3c392be751 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -794,8 +794,6 @@ void QQuickTextControl::timerEvent(QTimerEvent *e)
d->cursorOn = !d->cursorOn;
d->repaintCursor();
- } else if (e->timerId() == d->tripleClickTimer.timerId()) {
- d->tripleClickTimer.stop();
}
}
@@ -1058,7 +1056,7 @@ void QQuickTextControlPrivate::mousePressEvent(QMouseEvent *e, const QPointF &po
commitPreedit();
#endif
- if (tripleClickTimer.isActive()
+ if ((e->timestamp() < (timestampAtLastDoubleClick + QGuiApplication::styleHints()->mouseDoubleClickInterval()))
&& ((pos - tripleClickPoint).toPoint().manhattanLength() < QGuiApplication::styleHints()->startDragDistance())) {
cursor.movePosition(QTextCursor::StartOfBlock);
@@ -1068,7 +1066,7 @@ void QQuickTextControlPrivate::mousePressEvent(QMouseEvent *e, const QPointF &po
anchorOnMousePress = QString();
- tripleClickTimer.stop();
+ timestampAtLastDoubleClick = 0; // do not enter this condition in case of 4(!) rapid clicks
} else {
int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
if (cursorPos == -1) {
@@ -1214,8 +1212,8 @@ void QQuickTextControlPrivate::mouseReleaseEvent(QMouseEvent *e, const QPointF &
QTextBlock block = q->blockWithMarkerAt(pos);
if (block == blockWithMarkerUnderMousePress) {
auto fmt = block.blockFormat();
- fmt.setMarker(fmt.marker() == QTextBlockFormat::Unchecked ?
- QTextBlockFormat::Checked : QTextBlockFormat::Unchecked);
+ fmt.setMarker(fmt.marker() == QTextBlockFormat::MarkerType::Unchecked ?
+ QTextBlockFormat::MarkerType::Checked : QTextBlockFormat::MarkerType::Unchecked);
cursor.setBlockFormat(fmt);
}
}
@@ -1267,7 +1265,7 @@ void QQuickTextControlPrivate::mouseDoubleClickEvent(QMouseEvent *e, const QPoin
selectedWordOnDoubleClick = cursor;
tripleClickPoint = pos;
- tripleClickTimer.start(QGuiApplication::styleHints()->mouseDoubleClickInterval(), q);
+ timestampAtLastDoubleClick = e->timestamp();
if (doEmit) {
selectionChanged();
#if QT_CONFIG(clipboard)
@@ -1399,7 +1397,7 @@ QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property) cons
return inputMethodQuery(property, QVariant());
}
-QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
+QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property, const QVariant &argument) const
{
Q_D(const QQuickTextControl);
QTextBlock block = d->cursor.block();
@@ -1509,7 +1507,7 @@ void QQuickTextControlPrivate::hoverEvent(QHoverEvent *e, const QPointF &pos)
emit q->markerHovered(block.isValid());
hoveredMarker = block.isValid();
if (hoveredMarker)
- qCDebug(DBG_HOVER_TRACE) << q << e->type() << pos << "hovered marker" << block.blockFormat().marker() << block.text();
+ qCDebug(DBG_HOVER_TRACE) << q << e->type() << pos << "hovered marker" << int(block.blockFormat().marker()) << block.text();
}
}
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index 3c7d48f918..41b8ed7821 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -174,7 +174,7 @@ public:
#if QT_CONFIG(im)
virtual QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
- Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
+ Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const;
#endif
virtual QMimeData *createMimeDataFromSelection() const;
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index 5648c31e21..d52200b49d 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -143,7 +143,7 @@ public:
QTextBlock blockWithMarkerUnderMousePress;
QBasicTimer cursorBlinkTimer;
- QBasicTimer tripleClickTimer;
+ ulong timestampAtLastDoubleClick = 0; // will only be set at a double click
#if QT_CONFIG(im)
int preeditCursor;
diff --git a/src/quick/items/qquicktextdocument.h b/src/quick/items/qquicktextdocument.h
index affa0ab4d6..bf9162755c 100644
--- a/src/quick/items/qquicktextdocument.h
+++ b/src/quick/items/qquicktextdocument.h
@@ -49,6 +49,7 @@ class QQuickTextDocumentPrivate;
class Q_QUICK_EXPORT QQuickTextDocument : public QObject
{
Q_OBJECT
+ QML_ANONYMOUS
public:
QQuickTextDocument(QQuickItem *parent);
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 7414d7fd6a..c4e9c0d316 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1074,7 +1074,7 @@ int QQuickTextEdit::positionAt(qreal x, qreal y) const
}
/*!
- \qmlmethod QtQuick::TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
+ \qmlmethod QtQuick::TextEdit::moveCursorSelection(int position, SelectionMode mode)
Moves the cursor to \a position and updates the selection according to the optional \a mode
parameter. (To only move the cursor, set the \l cursorPosition property.)
@@ -1085,7 +1085,7 @@ int QQuickTextEdit::positionAt(qreal x, qreal y) const
text range.
The selection mode specifies whether the selection is updated on a per character or a per word
- basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
+ basis. If not specified the selection mode will default to \c {TextEdit.SelectCharacters}.
\list
\li TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
@@ -2828,7 +2828,7 @@ QString QQuickTextEdit::getFormattedText(int start, int end) const
/*!
\qmlmethod QtQuick::TextEdit::insert(int position, string text)
- Inserts \a text into the TextEdit at position.
+ Inserts \a text into the TextEdit at \a position.
*/
void QQuickTextEdit::insert(int position, const QString &text)
{
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index 2d1b6c7f9c..227d8cbf51 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -112,6 +112,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
Q_PROPERTY(QString preeditText READ preeditText NOTIFY preeditTextChanged REVISION 7)
Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance NOTIFY tabStopDistanceChanged REVISION 10)
+ QML_NAMED_ELEMENT(TextEdit)
public:
QQuickTextEdit(QQuickItem *parent=nullptr);
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 598ebb7a68..34105d8c81 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1359,8 +1359,8 @@ void QQuickTextInput::createCursor()
/*!
\qmlmethod rect QtQuick::TextInput::positionToRectangle(int pos)
- This function takes a character position and returns the rectangle that the
- cursor would occupy, if it was placed at that character position.
+ This function takes a character position \a pos and returns the rectangle
+ that the cursor would occupy, if it was placed at that character position.
This is similar to setting the cursorPosition, and then querying the cursor
rectangle, but the cursorPosition is not changed.
@@ -1390,10 +1390,10 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const
}
/*!
- \qmlmethod int QtQuick::TextInput::positionAt(real x, real y, CursorPosition position = CursorBetweenCharacters)
+ \qmlmethod int QtQuick::TextInput::positionAt(real x, real y, CursorPosition position)
This function returns the character position at
- x and y pixels from the top left of the textInput. Position 0 is before the
+ \a x and \a y pixels from the top left of the textInput. Position 0 is before the
first character, position 1 is after the first character but before the second,
and so on until position text.length, which is after all characters.
@@ -1403,12 +1403,13 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const
the first line and if it is below the text the position of the nearest character
on the last line will be returned.
- The cursor position type specifies how the cursor position should be resolved.
+ The cursor \a position parameter specifies how the cursor position should be resolved:
- \list
- \li TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
- \li TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
- \endlist
+ \value TextInput.CursorBetweenCharacters
+ Returns the position between characters that is nearest x.
+ This is the default value.
+ \value TextInput.CursorOnCharacter
+ Returns the position before the character that is nearest x.
*/
void QQuickTextInput::positionAt(QQmlV4Function *args) const
@@ -1957,7 +1958,7 @@ QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
return inputMethodQuery(property, QVariant());
}
-QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
+QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property, const QVariant &argument) const
{
Q_D(const QQuickTextInput);
switch (property) {
@@ -2132,7 +2133,7 @@ void QQuickTextInput::redo()
/*!
\qmlmethod QtQuick::TextInput::insert(int position, string text)
- Inserts \a text into the TextInput at position.
+ Inserts \a text into the TextInput at \a position.
*/
void QQuickTextInput::insert(int position, const QString &text)
@@ -2539,7 +2540,7 @@ void QQuickTextInput::moveCursorSelection(int position)
}
/*!
- \qmlmethod QtQuick::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
+ \qmlmethod QtQuick::TextInput::moveCursorSelection(int position, SelectionMode mode)
Moves the cursor to \a position and updates the selection according to the optional \a mode
parameter. (To only move the cursor, set the \l cursorPosition property.)
@@ -2550,7 +2551,7 @@ void QQuickTextInput::moveCursorSelection(int position)
text range.
The selection mode specifies whether the selection is updated on a per character or a per word
- basis. If not specified the selection mode will default to TextInput.SelectCharacters.
+ basis. If not specified the selection mode will default to \c {TextInput.SelectCharacters}.
\list
\li TextInput.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 92f3aa62ce..9f7b82b168 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -113,6 +113,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6)
Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6)
Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
+ QML_NAMED_ELEMENT(TextInput)
public:
QQuickTextInput(QQuickItem * parent=nullptr);
@@ -268,7 +269,7 @@ public:
#if QT_CONFIG(im)
QVariant inputMethodQuery(Qt::InputMethodQuery property) const override;
- Q_REVISION(4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
+ Q_REVISION(4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const;
#endif
QRectF boundingRect() const override;
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index c4a8370f34..a0ae4e5f97 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -638,7 +638,7 @@ void QQuickTextNodeEngine::addBorder(const QRectF &rect, qreal border,
QTextFrameFormat::BorderStyle borderStyle,
const QBrush &borderBrush)
{
- QColor color = borderBrush.color();
+ const QColor &color = borderBrush.color();
// Currently we don't support other styles than solid
Q_UNUSED(borderStyle);
@@ -781,8 +781,8 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
for (int i = 0; i < m_backgrounds.size(); ++i) {
const QRectF &rect = m_backgrounds.at(i).first;
const QColor &color = m_backgrounds.at(i).second;
-
- parentNode->addRectangleNode(rect, color);
+ if (color.alpha() != 0)
+ parentNode->addRectangleNode(rect, color);
}
// Add all text with unselected color first
@@ -1012,13 +1012,13 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
};
switch (block.blockFormat().marker()) {
- case QTextBlockFormat::Checked:
+ case QTextBlockFormat::MarkerType::Checked:
listItemBullet = QChar(0x2612); // Checked checkbox
break;
- case QTextBlockFormat::Unchecked:
+ case QTextBlockFormat::MarkerType::Unchecked:
listItemBullet = QChar(0x2610); // Unchecked checkbox
break;
- case QTextBlockFormat::NoMarker:
+ case QTextBlockFormat::MarkerType::NoMarker:
break;
}
diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h
index b6ea43342c..aeda6ca589 100644
--- a/src/quick/items/qquicktranslate_p.h
+++ b/src/quick/items/qquicktranslate_p.h
@@ -64,6 +64,7 @@ class Q_AUTOTEST_EXPORT QQuickTranslate : public QQuickTransform
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+ QML_NAMED_ELEMENT(Translate)
public:
QQuickTranslate(QObject *parent = nullptr);
@@ -95,6 +96,7 @@ class Q_AUTOTEST_EXPORT QQuickScale : public QQuickTransform
Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY xScaleChanged)
Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY yScaleChanged)
Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY zScaleChanged)
+ QML_NAMED_ELEMENT(Scale)
public:
QQuickScale(QObject *parent = nullptr);
~QQuickScale();
@@ -132,6 +134,7 @@ class Q_AUTOTEST_EXPORT QQuickRotation : public QQuickTransform
Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged)
+ QML_NAMED_ELEMENT(Rotation)
public:
QQuickRotation(QObject *parent = nullptr);
~QQuickRotation();
@@ -163,6 +166,8 @@ class Q_AUTOTEST_EXPORT QQuickMatrix4x4 : public QQuickTransform
Q_OBJECT
Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix NOTIFY matrixChanged)
+ QML_NAMED_ELEMENT(Matrix4x4)
+ QML_ADDED_IN_MINOR_VERSION(3)
public:
QQuickMatrix4x4(QObject *parent = nullptr);
~QQuickMatrix4x4();
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 51bcdbf352..ea1a74ef26 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -102,6 +102,7 @@ Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty")
Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient")
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+extern Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1);
bool QQuickWindowPrivate::defaultAlphaBuffer = false;
@@ -424,6 +425,13 @@ void QQuickWindowPrivate::syncSceneGraph()
{
Q_Q(QQuickWindow);
+ // Calculate the dpr the same way renderSceneGraph() will.
+ qreal devicePixelRatio = q->effectiveDevicePixelRatio();
+ if (renderTargetId && !QQuickRenderControl::renderWindowFor(q))
+ devicePixelRatio = 1;
+
+ context->prepareSync(devicePixelRatio);
+
animationController->beforeNodeSync();
emit q->beforeSynchronizing();
@@ -500,10 +508,10 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa
renderer->setDeviceRect(rect);
renderer->setViewportRect(rect);
if (QQuickRenderControl::renderWindowFor(q)) {
- renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size), false);
+ renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size));
renderer->setDevicePixelRatio(devicePixelRatio);
} else {
- renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), rect.size()), false);
+ renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), rect.size()));
renderer->setDevicePixelRatio(1);
}
} else {
@@ -520,7 +528,10 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa
renderer->setDeviceRect(rect);
renderer->setViewportRect(rect);
const bool flipY = rhi ? !rhi->isYUpInNDC() : false;
- renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), logicalSize), flipY);
+ QSGAbstractRenderer::MatrixTransformFlags matrixFlags = 0;
+ if (flipY)
+ matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY;
+ renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), logicalSize), matrixFlags);
renderer->setDevicePixelRatio(devicePixelRatio);
}
@@ -641,7 +652,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
q->setVulkanInstance(QSGRhiSupport::vulkanInstance());
#endif
- animationController = new QQuickAnimatorController(q);
+ animationController.reset(new QQuickAnimatorController(q));
QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection);
@@ -1784,6 +1795,13 @@ void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e)
{
if (activeFocusItem) {
QQuickItem *item = activeFocusItem;
+
+ // In case of generated event, trigger ShortcutOverride event
+ if (e->type() == QEvent::KeyPress && e->spontaneous() == false)
+ qt_sendShortcutOverrideEvent(item, e->timestamp(),
+ e->key(), e->modifiers(), e->text(),
+ e->isAutoRepeat(), e->count());
+
e->accept();
QCoreApplication::sendEvent(item, e);
while (!e->isAccepted() && (item = item->parentItem())) {
@@ -2758,7 +2776,7 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
// If the touch was accepted (regardless by whom or in what form),
// update accepted new points.
bool isPressOrRelease = pointerEvent->isPressEvent() || pointerEvent->isReleaseEvent();
- for (auto point: qAsConst(touchEvent->touchPoints())) {
+ for (const auto &point: qAsConst(touchEvent->touchPoints())) {
if (auto pointerEventPoint = ptEvent->pointById(point.id())) {
pointerEventPoint->setAccepted();
if (isPressOrRelease)
@@ -2768,7 +2786,7 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
} else {
// But if the event was not accepted then we know this item
// will not be interested in further updates for those touchpoint IDs either.
- for (auto point: qAsConst(touchEvent->touchPoints())) {
+ for (const auto &point: qAsConst(touchEvent->touchPoints())) {
if (point.state() == Qt::TouchPointPressed) {
if (auto *tp = ptEvent->pointById(point.id())) {
if (tp->exclusiveGrabber() == item) {
@@ -2810,32 +2828,49 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e
for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
QCoreApplication::sendEvent(**grabItem, &leaveEvent);
return;
- } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
+ } else {
QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
- if (deliverDragEvent(grabber, **grabItem, moveEvent)) {
- for (++grabItem; grabItem != grabber->end();) {
- QPointF p = (**grabItem)->mapFromScene(moveEvent->pos());
- if ((**grabItem)->contains(p)) {
- QDragMoveEvent translatedEvent(
- p.toPoint(),
- moveEvent->possibleActions(),
- moveEvent->mimeData(),
- moveEvent->mouseButtons(),
- moveEvent->keyboardModifiers());
- QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
- QCoreApplication::sendEvent(**grabItem, &translatedEvent);
- ++grabItem;
- } else {
- QDragLeaveEvent leaveEvent;
- QCoreApplication::sendEvent(**grabItem, &leaveEvent);
- grabItem = grabber->release(grabItem);
- }
+
+ // Used to ensure we don't send DragEnterEvents to current drop targets,
+ // and to detect which current drop targets we have left
+ QVarLengthArray<QQuickItem*, 64> currentGrabItems;
+ for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
+ currentGrabItems.append(**grabItem);
+
+ // Look for any other potential drop targets that are higher than the current ones
+ QDragEnterEvent enterEvent(
+ moveEvent->pos(),
+ moveEvent->possibleActions(),
+ moveEvent->mimeData(),
+ moveEvent->mouseButtons(),
+ moveEvent->keyboardModifiers());
+ QQuickDropEventEx::copyActions(&enterEvent, *moveEvent);
+ event->setAccepted(deliverDragEvent(grabber, contentItem, &enterEvent, &currentGrabItems));
+
+ for (grabItem = grabber->begin(); grabItem != grabber->end(); ++grabItem) {
+ int i = currentGrabItems.indexOf(**grabItem);
+ if (i >= 0) {
+ currentGrabItems.remove(i);
+ // Still grabbed: send move event
+ QDragMoveEvent translatedEvent(
+ (**grabItem)->mapFromScene(moveEvent->pos()).toPoint(),
+ moveEvent->possibleActions(),
+ moveEvent->mimeData(),
+ moveEvent->mouseButtons(),
+ moveEvent->keyboardModifiers());
+ QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
+ QCoreApplication::sendEvent(**grabItem, &translatedEvent);
+ event->setAccepted(translatedEvent.isAccepted());
+ QQuickDropEventEx::copyActions(moveEvent, translatedEvent);
}
- return;
- } else {
- QDragLeaveEvent leaveEvent;
- QCoreApplication::sendEvent(**grabItem, &leaveEvent);
}
+
+ // Anything left in currentGrabItems is no longer a drop target and should be sent a DragLeaveEvent
+ QDragLeaveEvent leaveEvent;
+ for (QQuickItem *i : currentGrabItems)
+ QCoreApplication::sendEvent(i, &leaveEvent);
+
+ return;
}
}
if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) {
@@ -2851,9 +2886,8 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e
}
}
-bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event)
+bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event, QVarLengthArray<QQuickItem*, 64> *currentGrabItems)
{
- bool accepted = false;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
if (!item->isVisible() || !item->isEnabled() || QQuickItemPrivate::get(item)->culled)
return false;
@@ -2872,12 +2906,24 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte
event->keyboardModifiers());
QQuickDropEventEx::copyActions(&enterEvent, *event);
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
+
+ // Check children in front of this item first
for (int ii = children.count() - 1; ii >= 0; --ii) {
- if (deliverDragEvent(grabber, children.at(ii), &enterEvent))
+ if (children.at(ii)->z() < 0)
+ continue;
+ if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems))
return true;
}
if (itemContained) {
+ // If this item is currently grabbed, don't send it another DragEnter,
+ // just grab it again if it's still contained.
+ if (currentGrabItems && currentGrabItems->contains(item)) {
+ grabber->grab(item);
+ grabber->setTarget(item);
+ return true;
+ }
+
if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) {
QDragMoveEvent translatedEvent(
p.toPoint(),
@@ -2894,15 +2940,24 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte
if (event->type() == QEvent::DragEnter) {
if (translatedEvent.isAccepted()) {
grabber->grab(item);
- accepted = true;
+ grabber->setTarget(item);
+ return true;
}
} else {
- accepted = true;
+ return true;
}
}
}
- return accepted;
+ // Check children behind this item if this item or any higher children have not accepted
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ if (children.at(ii)->z() >= 0)
+ continue;
+ if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems))
+ return true;
+ }
+
+ return false;
}
#endif // quick_draganddrop
@@ -3009,7 +3064,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event
if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) {
qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent;
skipDelivery.append(filteringParent);
- for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) {
+ for (const auto &point: qAsConst(filteringParentTouchEvent->touchPoints())) {
QQuickEventPoint *pt = event->pointById(point.id());
pt->setAccepted();
pt->setGrabberItem(filteringParent);
@@ -3114,6 +3169,18 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent
return overThreshold;
}
+bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold)
+{
+ QStyleHints *styleHints = qApp->styleHints();
+ bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
+ const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
+ if (!overThreshold && dragVelocityLimitAvailable) {
+ qreal velocity = axis == Qt::XAxis ? tp->velocity().x() : tp->velocity().y();
+ overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
+ }
+ return overThreshold;
+}
+
bool QQuickWindowPrivate::dragOverThreshold(QVector2D delta)
{
int threshold = qApp->styleHints()->startDragDistance();
@@ -4193,7 +4260,11 @@ QQmlIncubationController *QQuickWindow::incubationController() const
command buffer, before via QSGRendererInterface. Note however that the
render pass (or passes) are already recorded at this point and it is not
possible to add more commands within the scenegraph's pass. Instead, use
- afterRenderPassRecording() for that.
+ afterRenderPassRecording() for that. This signal has therefore limited use
+ and is rarely needed in an RHI-based setup. Rather, it is the combination
+ of beforeRendering() + beforeRenderPassRecording() or beforeRendering() +
+ afterRenderPassRecording() that is typically used to achieve under- or
+ overlaying of the custom rendering.
\warning This signal is emitted from the scene graph rendering thread. If your
slot function needs to finish before execution continues, you must make sure that
@@ -4229,7 +4300,7 @@ QQmlIncubationController *QQuickWindow::incubationController() const
\note Resource updates (uploads, copies) typically cannot be enqueued from
within a render pass. Therefore, more complex user rendering will need to
- connect to both the beforeRendering() and this signals.
+ connect to both beforeRendering() and this signal.
\warning This signal is emitted from the scene graph rendering thread. If your
slot function needs to finish before execution continues, you must make sure that
@@ -4260,7 +4331,7 @@ QQmlIncubationController *QQuickWindow::incubationController() const
\note Resource updates (uploads, copies) typically cannot be enqueued from
within a render pass. Therefore, more complex user rendering will need to
- connect to both the beforeRendering() and this signals.
+ connect to both beforeRendering() and this signal.
\warning This signal is emitted from the scene graph rendering thread. If your
slot function needs to finish before execution continues, you must make sure that
@@ -4733,7 +4804,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \return a pointer to a GraphicsStateInfo struct describing some of the
+ \return a reference to a GraphicsStateInfo struct describing some of the
RHI's internal state, in particular, the double or tripple buffering status
of the backend (such as, the Vulkan or Metal integrations). This is
relevant when the underlying graphics APIs is Vulkan or Metal, and the
@@ -4741,14 +4812,14 @@ void QQuickWindow::resetOpenGLState()
its own often-changing resources, such as, uniform buffers, in order to
avoid stalling the pipeline.
*/
-const QQuickWindow::GraphicsStateInfo *QQuickWindow::graphicsStateInfo()
+const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo()
{
Q_D(QQuickWindow);
if (d->rhi) {
d->rhiStateInfo.currentFrameSlot = d->rhi->currentFrameSlot();
d->rhiStateInfo.framesInFlight = d->rhi->resourceLimit(QRhi::FramesInFlight);
}
- return &d->rhiStateInfo;
+ return d->rhiStateInfo;
}
/*!
@@ -4773,6 +4844,17 @@ const QQuickWindow::GraphicsStateInfo *QQuickWindow::graphicsStateInfo()
because the scene graph performs the necessary steps implicitly for render
nodes.
+ Native graphics objects (such as, graphics device, command buffer or
+ encoder) are accessible via QSGRendererInterface::getResource().
+
+ \warning Watch out for the fact that
+ QSGRendererInterface::CommandListResource may return a different object
+ between beginExternalCommands() - endExternalCommands(). This can happen
+ when the underlying implementation provides a dedicated secondary command
+ buffer for recording external graphics commands within a render pass.
+ Therefore, always query CommandListResource after calling this function. Do
+ not attempt to reuse an object from an earlier query.
+
\note This function has no effect when the scene graph is using OpenGL
directly and the RHI graphics abstraction layer is not in use. Refer to
resetOpenGLState() in that case.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 9dbff88f0d..bec1ace2a6 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -76,6 +76,9 @@ class Q_QUICK_EXPORT QQuickWindow : public QWindow
Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT)
Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged REVISION 1)
Q_CLASSINFO("DefaultProperty", "data")
+ QML_NAMED_ELEMENT(Window)
+ QML_ADDED_IN_MINOR_VERSION(0)
+ QML_REMOVED_IN_MINOR_VERSION(1)
Q_DECLARE_PRIVATE(QQuickWindow)
public:
enum CreateTextureOption {
@@ -142,10 +145,10 @@ public:
void resetOpenGLState();
#endif
struct GraphicsStateInfo {
- int currentFrameSlot = 0;
- int framesInFlight = 0;
+ int currentFrameSlot;
+ int framesInFlight;
};
- const GraphicsStateInfo *graphicsStateInfo();
+ const GraphicsStateInfo &graphicsStateInfo();
void beginExternalCommands();
void endExternalCommands();
QQmlIncubationController *incubationController() const;
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index becbae7fe3..af7d65dac5 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -192,7 +192,7 @@ public:
#if QT_CONFIG(quick_draganddrop)
void deliverDragEvent(QQuickDragGrabber *, QEvent *);
- bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *);
+ bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *, QVarLengthArray<QQuickItem*, 64> *currentGrabItems = nullptr);
#endif
#if QT_CONFIG(cursor)
void updateCursor(const QPointF &scenePos);
@@ -254,7 +254,7 @@ public:
QSGRenderLoop *windowManager;
QQuickRenderControl *renderControl;
- QQuickAnimatorController *animationController;
+ QScopedPointer<QQuickAnimatorController> animationController;
QScopedPointer<QTouchEvent> delayedTouch;
int pointerEventRecursionGuard;
@@ -288,25 +288,7 @@ public:
static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1);
- template <typename TEventPoint>
- static bool dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint *p, int startDragThreshold = -1)
- {
- QStyleHints *styleHints = qApp->styleHints();
- bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
- const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
- if (!overThreshold && dragVelocityLimitAvailable) {
- qreal velocity = axis == Qt::XAxis ? p->velocity().x() : p->velocity().y();
- overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
- }
- return overThreshold;
- }
-
- static bool dragOverThreshold(const QQuickEventPoint *point)
- {
- QPointF delta = point->scenePosition() - point->scenePressPosition();
- return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) ||
- QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point));
- }
+ static bool dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold = -1);
static bool dragOverThreshold(QVector2D delta);
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index 4b2b8f498d..0f952d194c 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -199,22 +199,13 @@ void QQuickWindowModule::defineModule()
{
const char uri[] = "QtQuick.Window";
- qmlRegisterType<QQuickWindow>(uri, 2, 0, "Window");
+ // Cannot automatically register these. They are from QtGui.
qmlRegisterRevision<QWindow,1>(uri, 2, 1);
qmlRegisterRevision<QWindow,2>(uri, 2, 2);
- qmlRegisterRevision<QQuickWindow,1>(uri, 2, 1);//Type moved to a subclass, but also has new members
- qmlRegisterRevision<QQuickWindow,2>(uri, 2, 2);
- qmlRegisterType<QQuickWindowQmlImpl>(uri, 2, 1, "Window");
- qmlRegisterType<QQuickWindowQmlImpl,2>(uri, 2, 2, "Window");
- qmlRegisterType<QQuickWindowQmlImpl,3>(uri, 2, 3, "Window");
- qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property."));
- qmlRegisterUncreatableType<QQuickScreen,3>(uri, 2, 3, "Screen", QStringLiteral("Screen can only be used via the attached property."));
- qmlRegisterUncreatableType<QQuickScreenInfo,3>(uri, 2, 3, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property."));
- qmlRegisterUncreatableType<QQuickScreenInfo,10>(uri, 2, 10, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property."));
qmlRegisterRevision<QWindow,13>(uri, 2, 13);
- qmlRegisterRevision<QQuickWindow,13>(uri, 2, 13);
- qmlRegisterType<QQuickWindowQmlImpl,13>(uri, 2, 13, "Window");
- qmlRegisterRevision<QQuickWindow,14>(uri, 2, 14);
+
+ qmlRegisterTypesAndRevisions<QQuickWindow, QQuickWindowQmlImpl,
+ QQuickScreen, QQuickScreenInfo>(uri, 2);
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h
index 1dcf1a1021..1769e5aeb4 100644
--- a/src/quick/items/qquickwindowmodule_p.h
+++ b/src/quick/items/qquickwindowmodule_p.h
@@ -68,6 +68,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickWindowQmlImpl : public QQuickWindow, public Q
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged)
Q_PROPERTY(QObject *screen READ screen WRITE setScreen NOTIFY screenChanged REVISION 3)
+ QML_NAMED_ELEMENT(Window)
+ QML_ADDED_IN_MINOR_VERSION(1)
+ QML_ATTACHED(QQuickWindowAttached)
public:
QQuickWindowQmlImpl(QWindow *parent = nullptr);
@@ -106,6 +109,5 @@ public:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickWindowQmlImpl)
-QML_DECLARE_TYPEINFO(QQuickWindowQmlImpl, QML_HAS_ATTACHED_PROPERTIES)
#endif
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 7a04c2146c..527742ab8a 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -185,8 +185,6 @@ void QQmlQtQuick2Module::defineModule()
QQuickUtilModule::defineModule();
QQuickItemsModule::defineModule();
- qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
-
QQuickValueTypes::registerValueTypes();
#if QT_CONFIG(accessibility)
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
index f5a41410ee..c97dcb9326 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
@@ -100,7 +100,7 @@ void QSGSoftwareRenderLoop::windowDestroyed(QQuickWindow *window)
rc->invalidate();
}
- delete d->animationController;
+ d->animationController.reset();
}
void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window, bool isNewExpose)
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp
index d4e5e98d68..17e8bdc2f9 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp
@@ -49,6 +49,11 @@ QSGSoftwareSpriteNode::QSGSoftwareSpriteNode()
setGeometry((QSGGeometry*)1);
}
+QSGSoftwareSpriteNode::~QSGSoftwareSpriteNode()
+{
+ delete m_texture;
+}
+
void QSGSoftwareSpriteNode::setTexture(QSGTexture *texture)
{
m_texture = qobject_cast<QSGSoftwarePixmapTexture*>(texture);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h
index 577a30c051..4015537395 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h
@@ -64,6 +64,7 @@ class QSGSoftwareSpriteNode : public QSGSpriteNode
{
public:
QSGSoftwareSpriteNode();
+ ~QSGSoftwareSpriteNode() override;
void setTexture(QSGTexture *texture) override;
void setTime(float time) override;
@@ -81,7 +82,7 @@ public:
private:
- QSGSoftwarePixmapTexture *m_texture;
+ QSGSoftwarePixmapTexture *m_texture = nullptr;
float m_time;
QPoint m_sourceA;
QPoint m_sourceB;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
index 2d4dcd928d..c6b463bb02 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
@@ -292,7 +292,7 @@ bool QSGSoftwareRenderThread::event(QEvent *e)
QCoreApplication::processEvents();
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
if (wme->destroying)
- delete wd->animationController;
+ wd->animationController.reset();
}
if (wme->destroying)
active = false;
@@ -844,7 +844,8 @@ void QSGSoftwareThreadedRenderLoop::handleExposure(QQuickWindow *window)
if (!w->thread->isRunning()) {
qCDebug(QSG_RASTER_LOG_RENDERLOOP, "starting render thread");
// Push a few things to the render thread.
- QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController;
+ QQuickAnimatorController *controller
+ = QQuickWindowPrivate::get(w->window)->animationController.get();
if (controller->thread() != w->thread)
controller->moveToThread(w->thread);
if (w->thread->thread() == QThread::currentThread()) {
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
index 679ad1d445..62ed342244 100644
--- a/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
@@ -73,6 +73,22 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \enum QSGAbstractRenderer::MatrixTransformFlag
+
+ Used with setProjectionMatrixToRect() to indicate the expectations towards
+ the generated projection matrix.
+
+ \value MatrixTransformFlipY The traditional assumption in Qt Quick is that
+ Y points up in the normalized device coordinate system. There is at least
+ one modern graphics API where this is not the case (Vulkan). This flag can
+ then be used to get a projection that is appropriate for such an API.
+
+ \sa setProjectionMatrixToRect()
+
+ \since 5.14
+ */
+
+/*!
\fn void QSGAbstractRenderer::renderScene(GLuint fboId = 0)
Render the scene to the specified \a fboId
@@ -224,14 +240,38 @@ QRect QSGAbstractRenderer::viewportRect() const
Convenience method that calls setProjectionMatrix() with an
orthographic matrix generated from \a rect.
- \a flipY must be \c true when the graphics API uses Y down in its
- normalized device coordinate system (for example, Vulkan), \c false
- otherwise.
+ \note This function assumes that the graphics API uses Y up in its
+ normalized device coordinate system.
\sa setProjectionMatrix(), projectionMatrix()
*/
-void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect, bool flipY)
+void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect)
+{
+ QMatrix4x4 matrix;
+ matrix.ortho(rect.x(),
+ rect.x() + rect.width(),
+ rect.y() + rect.height(),
+ rect.y(),
+ 1,
+ -1);
+ setProjectionMatrix(matrix);
+ setProjectionMatrixWithNativeNDC(matrix);
+}
+
+/*!
+ Convenience method that calls setProjectionMatrix() with an
+ orthographic matrix generated from \a rect.
+
+ Set MatrixTransformFlipY in \a flags when the graphics API uses Y down in
+ its normalized device coordinate system (for example, Vulkan).
+
+ \sa setProjectionMatrix(), projectionMatrix()
+
+ \since 5.14
+ */
+void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags)
{
+ const bool flipY = flags.testFlag(MatrixTransformFlipY);
QMatrix4x4 matrix;
matrix.ortho(rect.x(),
rect.x() + rect.width(),
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h
index 08e600e0b8..1594352dab 100644
--- a/src/quick/scenegraph/coreapi/qsgabstractrenderer.h
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h
@@ -63,6 +63,13 @@ public:
Q_DECLARE_FLAGS(ClearMode, ClearModeBit)
Q_FLAG(ClearMode)
+ enum MatrixTransformFlag
+ {
+ MatrixTransformFlipY = 0x01
+ };
+ Q_DECLARE_FLAGS(MatrixTransformFlags, MatrixTransformFlag)
+ Q_FLAG(MatrixTransformFlags)
+
~QSGAbstractRenderer() override;
void setRootNode(QSGRootNode *node);
@@ -75,7 +82,8 @@ public:
inline void setViewportRect(const QSize &size) { setViewportRect(QRect(QPoint(), size)); }
QRect viewportRect() const;
- void setProjectionMatrixToRect(const QRectF &rect, bool flipY = false);
+ void setProjectionMatrixToRect(const QRectF &rect);
+ void setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags);
void setProjectionMatrix(const QMatrix4x4 &matrix);
void setProjectionMatrixWithNativeNDC(const QMatrix4x4 &matrix);
QMatrix4x4 projectionMatrix() const;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index a566a2bed6..45b00d43c4 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -187,7 +187,7 @@ static QRhiVertexInputLayout calculateVertexInputLayout(const QSGMaterialRhiShad
}
const int attrCount = geometry->attributeCount();
- QVector<QRhiVertexInputAttribute> inputAttributes;
+ QVarLengthArray<QRhiVertexInputAttribute, 8> inputAttributes;
inputAttributes.reserve(attrCount + 1);
int offset = 0;
for (int i = 0; i < attrCount; ++i) {
@@ -205,15 +205,14 @@ static QRhiVertexInputLayout calculateVertexInputLayout(const QSGMaterialRhiShad
}
Q_ASSERT(VERTEX_BUFFER_BINDING == 0 && ZORDER_BUFFER_BINDING == 1); // not very flexible
- QVector<QRhiVertexInputBinding> inputBindings;
- inputBindings.reserve(2);
+ QVarLengthArray<QRhiVertexInputBinding, 2> inputBindings;
inputBindings.append(QRhiVertexInputBinding(geometry->sizeOfVertex()));
if (batchable)
inputBindings.append(QRhiVertexInputBinding(sizeof(float)));
QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings(inputBindings);
- inputLayout.setAttributes(inputAttributes);
+ inputLayout.setBindings(inputBindings.cbegin(), inputBindings.cend());
+ inputLayout.setAttributes(inputAttributes.cbegin(), inputAttributes.cend());
return inputLayout;
}
@@ -400,14 +399,14 @@ void ShaderManager::clearCachedRendererData()
}
}
-QRhiShaderResourceBindings *ShaderManager::srb(const QVector<QRhiShaderResourceBinding> &bindings)
+QRhiShaderResourceBindings *ShaderManager::srb(const ShaderResourceBindingList &bindings)
{
auto it = srbCache.constFind(bindings);
if (it != srbCache.constEnd())
return *it;
QRhiShaderResourceBindings *srb = context->rhi()->newShaderResourceBindings();
- srb->setBindings(bindings);
+ srb->setBindings(bindings.cbegin(), bindings.cend());
if (srb->build()) {
srbCache.insert(bindings, srb);
} else {
@@ -1123,6 +1122,9 @@ void Renderer::releaseCachedResources()
m_pipelines.clear();
m_samplers.clear();
m_dummyTexture = nullptr;
+
+ if (m_rhi)
+ m_rhi->releaseCachedResources();
}
void Renderer::invalidateAndRecycleBatch(Batch *b)
@@ -2846,7 +2848,7 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch) // RHI
else {
if (qsg_topology(g->drawingMode()) != m_stencilClipCommon.topology)
qWarning("updateClipState: Clip list entries have different primitive topologies, this is not currently supported.");
- if (qsg_vertexInputFormat(*a) != m_stencilClipCommon.inputLayout.attributes().first().format())
+ if (qsg_vertexInputFormat(*a) != m_stencilClipCommon.inputLayout.cbeginAttributes()->format())
qWarning("updateClipState: Clip list entries have different vertex input layouts, this is must not happen.");
}
#endif
@@ -3250,7 +3252,7 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms)
// Build a new one. This is potentially expensive.
QRhiGraphicsPipeline *ps = m_rhi->newGraphicsPipeline();
- ps->setShaderStages(sms->programRhi.shaderStages);
+ ps->setShaderStages(sms->programRhi.shaderStages.cbegin(), sms->programRhi.shaderStages.cend());
ps->setVertexInputLayout(sms->programRhi.inputLayout);
ps->setShaderResourceBindings(e->srb);
ps->setRenderPassDescriptor(renderPassDescriptor());
@@ -3423,9 +3425,9 @@ static void materialToRendererGraphicsState(GraphicsState *dst,
}
void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
- const QSGMaterialRhiShader::RenderState &renderState,
+ QSGMaterialRhiShader::RenderState &renderState,
QSGMaterial *material,
- QVector<QRhiShaderResourceBinding> *bindings,
+ ShaderManager::ShaderResourceBindingList *bindings,
const Batch *batch,
int ubufOffset,
int ubufRegionSize) // RHI only, [prepare step]
@@ -3437,6 +3439,7 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
if (pd->ubufBinding >= 0) {
m_current_uniform_data = &pd->masterUniformData;
const bool changed = shader->updateUniformData(renderState, material, m_currentMaterial);
+ m_current_uniform_data = nullptr;
if (changed || !batch->ubufDataValid)
m_resourceUpdates->updateDynamicBuffer(batch->ubuf, ubufOffset, ubufRegionSize, pd->masterUniformData.constData());
@@ -3513,7 +3516,7 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
}
void Renderer::updateMaterialStaticData(ShaderManager::Shader *sms,
- const QSGMaterialRhiShader::RenderState &renderState,
+ QSGMaterialRhiShader::RenderState &renderState,
QSGMaterial *material,
Batch *batch,
bool *gstateChanged) // RHI only, [prepare step]
@@ -3621,12 +3624,12 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende
}
}
- const QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty)));
+ QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty)));
bool pendingGStatePop = false;
updateMaterialStaticData(sms, renderState, material, batch, &pendingGStatePop);
- QVector<QRhiShaderResourceBinding> bindings;
+ ShaderManager::ShaderResourceBindingList bindings;
updateMaterialDynamicData(sms, renderState, material, &bindings, batch, 0, ubufSize);
#ifndef QT_NO_DEBUG
@@ -3798,8 +3801,9 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
}
}
+ QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty)));
bool pendingGStatePop = false;
- updateMaterialStaticData(sms, rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))),
+ updateMaterialStaticData(sms, renderState,
material, batch, &pendingGStatePop);
int ubufOffset = 0;
@@ -3818,8 +3822,9 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange;
}
- QVector<QRhiShaderResourceBinding> bindings;
- updateMaterialDynamicData(sms, rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))),
+ QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty)));
+ ShaderManager::ShaderResourceBindingList bindings;
+ updateMaterialDynamicData(sms, renderState,
material, &bindings, batch, ubufOffset, ubufSize);
#ifndef QT_NO_DEBUG
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 4e374522d4..297df2232a 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -642,7 +642,7 @@ public:
struct {
QSGMaterialRhiShader *program = nullptr;
QRhiVertexInputLayout inputLayout;
- QVector<QRhiGraphicsShaderStage> shaderStages;
+ QVarLengthArray<QRhiGraphicsShaderStage, 2> shaderStages;
} programRhi;
float lastOpacity;
@@ -656,7 +656,9 @@ public:
void clearCachedRendererData();
- QRhiShaderResourceBindings *srb(const QVector<QRhiShaderResourceBinding> &bindings);
+ using ShaderResourceBindingList = QVarLengthArray<QRhiShaderResourceBinding, 8>;
+
+ QRhiShaderResourceBindings *srb(const ShaderResourceBindingList &bindings);
public Q_SLOTS:
void invalidated();
@@ -672,7 +674,7 @@ private:
QOpenGLShaderProgram *blitProgram;
QSGDefaultRenderContext *context;
- QHash<QVector<QRhiShaderResourceBinding>, QRhiShaderResourceBindings *> srbCache;
+ QHash<ShaderResourceBindingList, QRhiShaderResourceBindings *> srbCache;
};
struct GraphicsState
@@ -796,10 +798,10 @@ private:
void renderBatches();
bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms);
QRhiTexture *dummyTexture();
- void updateMaterialDynamicData(ShaderManager::Shader *sms, const QSGMaterialRhiShader::RenderState &renderState,
- QSGMaterial *material, QVector<QRhiShaderResourceBinding> *bindings,
+ void updateMaterialDynamicData(ShaderManager::Shader *sms, QSGMaterialRhiShader::RenderState &renderState,
+ QSGMaterial *material, ShaderManager::ShaderResourceBindingList *bindings,
const Batch *batch, int ubufOffset, int ubufRegionSize);
- void updateMaterialStaticData(ShaderManager::Shader *sms, const QSGMaterialRhiShader::RenderState &renderState,
+ void updateMaterialStaticData(ShaderManager::Shader *sms, QSGMaterialRhiShader::RenderState &renderState,
QSGMaterial *material, Batch *batch, bool *gstateChanged);
void checkLineWidth(QSGGeometry *g);
bool prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *renderBatch);
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index 5218b6b1d5..a28eee5288 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
@@ -576,6 +576,10 @@ const void *QSGGeometry::indexData() const
\value IntType
\value UnsignedIntType
\value FloatType
+ \value Bytes2Type Added in Qt 5.14.
+ \value Bytes3Type Added in Qt 5.14.
+ \value Bytes4Type Added in Qt 5.14.
+ \value DoubleType Added in Qt 5.14.
*/
/*!
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp
index 03f74df6b7..117d477f9a 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp
@@ -301,9 +301,9 @@ void QSGMaterialRhiShader::setFlag(Flags flags, bool on)
memcpy calls) when updating material states. When \a oldMaterial is null,
this shader was just activated.
*/
-bool QSGMaterialRhiShader::updateUniformData(const RenderState &state,
- QSGMaterial *newMaterial,
- QSGMaterial *oldMaterial)
+bool QSGMaterialRhiShader::updateUniformData(RenderState &state,
+ QSGMaterial *newMaterial,
+ QSGMaterial *oldMaterial)
{
Q_UNUSED(state);
Q_UNUSED(newMaterial);
@@ -334,11 +334,11 @@ bool QSGMaterialRhiShader::updateUniformData(const RenderState &state,
\a oldMaterial can be used to minimize changes. When \a oldMaterial is null,
this shader was just activated.
*/
-void QSGMaterialRhiShader::updateSampledImage(const RenderState &state,
- int binding,
- QSGTexture **texture,
- QSGMaterial *newMaterial,
- QSGMaterial *oldMaterial)
+void QSGMaterialRhiShader::updateSampledImage(RenderState &state,
+ int binding,
+ QSGTexture **texture,
+ QSGMaterial *newMaterial,
+ QSGMaterial *oldMaterial)
{
Q_UNUSED(state);
Q_UNUSED(binding);
@@ -367,8 +367,8 @@ void QSGMaterialRhiShader::updateSampledImage(const RenderState &state,
The subclass specific state can be extracted from \a newMaterial. When \a
oldMaterial is null, this shader was just activated.
*/
-bool QSGMaterialRhiShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps,
- QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+bool QSGMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
+ QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_UNUSED(state);
Q_UNUSED(ps);
@@ -426,12 +426,77 @@ bool QSGMaterialRhiShader::updateGraphicsPipelineState(const RenderState &state,
*/
/*!
+ \class QSGMaterialRhiShader::GraphicsPipelineState
+
+ \brief Describes state changes that the material wants to apply to the
+ currently active graphics pipeline state.
+
+ \inmodule QtQuick
+ \since 5.14
+
+ Unlike QSGMaterialShader, directly issuing state change commands with the
+ underlying graphics API is not possible with QSGMaterialRhiShader. This is
+ mainly because the concept of individually changeable states is considered
+ deprecated and not supported with modern graphics APIs.
+
+ Therefore, it is up to QSGMaterialRhiShader to expose a data structure with
+ the set of supported states, which the material can change in its
+ updatePipelineState() implementation, if there is one. The scenegraph will
+ then internally apply these changes to the active graphics pipeline state,
+ then rolling them back as appropriate.
+ */
+
+/*!
+ \enum QSGMaterialRhiShader::GraphicsPipelineState::BlendFactor
+ \since 5.14
+
+ \value Zero
+ \value One
+ \value SrcColor
+ \value OneMinusSrcColor
+ \value DstColor
+ \value OneMinusDstColor
+ \value SrcAlpha
+ \value OneMinusSrcAlpha
+ \value DstAlpha
+ \value OneMinusDstAlpha
+ \value ConstantColor
+ \value OneMinusConstantColor
+ \value ConstantAlpha
+ \value OneMinusConstantAlpha
+ \value SrcAlphaSaturate
+ \value Src1Color
+ \value OneMinusSrc1Color
+ \value Src1Alpha
+ \value OneMinusSrc1Alpha
+ */
+
+/*!
+ \enum QSGMaterialRhiShader::GraphicsPipelineState::ColorMaskComponent
+ \since 5.14
+
+ \value R
+ \value G
+ \value B
+ \value A
+ */
+
+/*!
+ \enum QSGMaterialRhiShader::GraphicsPipelineState::CullMode
+ \since 5.14
+
+ \value CullNone
+ \value CullFront
+ \value CullBack
+ */
+
+/*!
Returns the accumulated opacity to be used for rendering.
*/
float QSGMaterialRhiShader::RenderState::opacity() const
{
Q_ASSERT(m_data);
- return static_cast<const QSGRenderer *>(m_data)->currentOpacity();
+ return float(static_cast<const QSGRenderer *>(m_data)->currentOpacity());
}
/*!
@@ -440,7 +505,7 @@ float QSGMaterialRhiShader::RenderState::opacity() const
float QSGMaterialRhiShader::RenderState::determinant() const
{
Q_ASSERT(m_data);
- return static_cast<const QSGRenderer *>(m_data)->determinant();
+ return float(static_cast<const QSGRenderer *>(m_data)->determinant());
}
/*!
@@ -459,7 +524,7 @@ QMatrix4x4 QSGMaterialRhiShader::RenderState::combinedMatrix() const
float QSGMaterialRhiShader::RenderState::devicePixelRatio() const
{
Q_ASSERT(m_data);
- return static_cast<const QSGRenderer *>(m_data)->devicePixelRatio();
+ return float(static_cast<const QSGRenderer *>(m_data)->devicePixelRatio());
}
/*!
@@ -511,7 +576,10 @@ QRect QSGMaterialRhiShader::RenderState::deviceRect() const
/*!
Returns a pointer to the data for the uniform (constant) buffer in the
- shader.
+ shader. Uniform data must only be updated from
+ QSGMaterialRhiShader::updateUniformData(). The return value is null in the
+ other reimplementable functions, such as,
+ QSGMaterialRhiShader::updateSampledImage().
\note It is strongly recommended to declare the uniform block with \c
std140 in the shader, and to carefully study the standard uniform block
@@ -525,11 +593,8 @@ QRect QSGMaterialRhiShader::RenderState::deviceRect() const
\note Avoid copying from C++ POD types, such as, structs, in order to
update multiple members at once, unless it has been verified that the
layouts of the C++ struct and the GLSL uniform block match.
-
- \note Uniform data must only be updated from
- QSGMaterialRhiShader::updateUniformData().
*/
-QByteArray *QSGMaterialRhiShader::RenderState::uniformData() const
+QByteArray *QSGMaterialRhiShader::RenderState::uniformData()
{
Q_ASSERT(m_data);
return static_cast<const QSGRenderer *>(m_data)->currentUniformData();
@@ -541,7 +606,7 @@ QByteArray *QSGMaterialRhiShader::RenderState::uniformData() const
QSGMaterialRhiShader::updateSampledImage() to enqueue texture image
content updates.
*/
-QRhiResourceUpdateBatch *QSGMaterialRhiShader::RenderState::resourceUpdateBatch() const
+QRhiResourceUpdateBatch *QSGMaterialRhiShader::RenderState::resourceUpdateBatch()
{
Q_ASSERT(m_data);
return static_cast<const QSGRenderer *>(m_data)->currentResourceUpdateBatch();
@@ -550,7 +615,7 @@ QRhiResourceUpdateBatch *QSGMaterialRhiShader::RenderState::resourceUpdateBatch(
/*!
Returns the current QRhi.
*/
-QRhi *QSGMaterialRhiShader::RenderState::rhi() const
+QRhi *QSGMaterialRhiShader::RenderState::rhi()
{
Q_ASSERT(m_data);
return static_cast<const QSGRenderer *>(m_data)->currentRhi();
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h
index 01991135ec..86208516cd 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h
@@ -76,9 +76,9 @@ public:
float determinant() const;
float devicePixelRatio() const;
- QByteArray *uniformData() const;
- QRhiResourceUpdateBatch *resourceUpdateBatch() const;
- QRhi *rhi() const;
+ QByteArray *uniformData();
+ QRhiResourceUpdateBatch *resourceUpdateBatch();
+ QRhi *rhi();
private:
friend class QSGRenderer;
@@ -146,13 +146,13 @@ public:
QSGMaterialRhiShader();
virtual ~QSGMaterialRhiShader();
- virtual bool updateUniformData(const RenderState &state,
+ virtual bool updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
- virtual void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+ virtual void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
- virtual bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps,
+ virtual bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
Flags flags() const;
diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp
index e504fe1c62..0fee1486cf 100644
--- a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp
@@ -78,11 +78,11 @@ QT_BEGIN_NAMESPACE
\value OpenGL OpenGL ES 2.0 or higher
\value Direct3D12 Direct3D 12
\value OpenVG OpenVG via EGL
- \value OpenGLRhi OpenGL ES 2.0 or higher via a graphics abstraction layer
- \value Direct3D11Rhi Direct3D 11 via a graphics abstraction layer
- \value VulkanRhi Vulkan 1.0 via a graphics abstraction layer
- \value MetalRhi Metal via a graphics abstraction layer
- \value NullRhi Null (no output) via a graphics abstraction layer
+ \value OpenGLRhi OpenGL ES 2.0 or higher via a graphics abstraction layer. This value was introduced in Qt 5.14.
+ \value Direct3D11Rhi Direct3D 11 via a graphics abstraction layer. This value was introduced in Qt 5.14.
+ \value VulkanRhi Vulkan 1.0 via a graphics abstraction layer. This value was introduced in Qt 5.14.
+ \value MetalRhi Metal via a graphics abstraction layer. This value was introduced in Qt 5.14.
+ \value NullRhi Null (no output) via a graphics abstraction layer. This value was introduced in Qt 5.14.
*/
/*!
@@ -111,29 +111,36 @@ QT_BEGIN_NAMESPACE
used by the scenegraph, when running with the software backend.
\value RhiResource The resource is a pointer to the QRhi instance used by
- the scenegraph, when applicable.
+ the scenegraph, when applicable. This value was introduced in Qt 5.14.
\value PhysicalDeviceResource The resource is a pointer to the pysical
device object used by the scenegraph, when applicable. For example, a
\c{VkPhysicalDevice *}. Note that with Vulkan the returned value is a
- pointer to the VkPhysicalDevice, not the handle itself.
+ pointer to the VkPhysicalDevice, not the handle itself. This value was
+ introduced in Qt 5.14.
\value OpenGLContextResource The resource is a pointer to the
QOpenGLContext used by the scenegraph (on the render thread), when
- applicable.
+ applicable. This value was introduced in Qt 5.14.
\value DeviceContextResource The resource is a pointer to the device
context used by the scenegraph, when applicable. For example, a
- \c{ID3D11DeviceContext *}.
+ \c{ID3D11DeviceContext *}. This value was introduced in Qt 5.14.
\value CommandEncoderResource The resource is a pointer to the currently
active render command encoder object used by the scenegraph, when
applicable. For example, a \c{MTLRenderCommandEncoder *}. This object has
limited validity, and is only valid while the scene graph is recording a
- render pass for the next frame.
+ render pass for the next frame. This value was introduced in Qt 5.14.
\value VulkanInstanceResource The resource is a pointer to the
- QVulkanInstance used by the scenegraph, when applicable.
+ QVulkanInstance used by the scenegraph, when applicable. This value was
+ introduced in Qt 5.14.
+
+ \value RenderPassResource The resource is a pointer to the render pass used
+ by the scenegraph, describing the color and depth/stecil attachments and
+ how they are used. For example, a \c{VkRenderPass *}. This value was
+ introduced in Qt 5.14.
*/
/*!
@@ -141,8 +148,9 @@ QT_BEGIN_NAMESPACE
\value UnknownShadingLanguage Not yet known due to no window and scenegraph associated
\value GLSL GLSL or GLSL ES
\value HLSL HLSL
- \value RhiShader Consumes QShader instances containing shader
- variants for multiple target languages and bytecode formats
+ \value RhiShader Consumes QShader instances containing shader variants for
+ multiple target languages and intermediate formats. This value was introduced in
+ Qt 5.14.
*/
/*!
@@ -218,6 +226,8 @@ void *QSGRendererInterface::getResource(QQuickWindow *window, const char *resour
instead of directly calling the native graphics API.
\note This function can be called on any thread.
+
+ \since 5.14
*/
bool QSGRendererInterface::isApiRhiBased(GraphicsApi api)
{
diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.h b/src/quick/scenegraph/coreapi/qsgrendererinterface.h
index 3052c81f6c..7aa7d0e769 100644
--- a/src/quick/scenegraph/coreapi/qsgrendererinterface.h
+++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.h
@@ -72,7 +72,8 @@ public:
OpenGLContextResource,
DeviceContextResource,
CommandEncoderResource,
- VulkanInstanceResource
+ VulkanInstanceResource,
+ RenderPassResource
};
enum ShaderType {
diff --git a/src/quick/scenegraph/coreapi/qsgtexture.cpp b/src/quick/scenegraph/coreapi/qsgtexture.cpp
index c47401e5c0..edcee96bdb 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture.cpp
+++ b/src/quick/scenegraph/coreapi/qsgtexture.cpp
@@ -717,6 +717,9 @@ void QSGTexture::updateRhiTexture(QRhi *rhi, QRhiResourceUpdateBatch *resourceUp
d->updateRhiTexture(rhi, resourceUpdates);
}
+/*!
+ \internal
+ */
void QSGTexture::setWorkResourceUpdateBatch(QRhiResourceUpdateBatch *resourceUpdates)
{
Q_D(QSGTexture);
diff --git a/src/quick/scenegraph/coreapi/qsgtexture.h b/src/quick/scenegraph/coreapi/qsgtexture.h
index 4cd2a5cddd..2efdd8b7c3 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture.h
+++ b/src/quick/scenegraph/coreapi/qsgtexture.h
@@ -141,6 +141,7 @@ class Q_QUICK_EXPORT QSGDynamicTexture : public QSGTexture
Q_OBJECT
public:
+ QSGDynamicTexture() = default;
virtual bool updateTexture() = 0;
protected:
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 97fd49e4c7..17eb1e312c 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -341,6 +341,11 @@ void QSGRenderContext::invalidate()
{
}
+void QSGRenderContext::prepareSync(qreal devicePixelRatio)
+{
+ Q_UNUSED(devicePixelRatio);
+}
+
void QSGRenderContext::beginNextFrame(QSGRenderer *renderer,
RenderPassCallback mainPassRecordingStart,
RenderPassCallback mainPassRecordingEnd,
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 4e712ab7c3..244bcfabd1 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -174,6 +174,7 @@ public:
using RenderPassCallback = void (*)(void *);
+ virtual void prepareSync(qreal devicePixelRatio);
virtual void beginNextFrame(QSGRenderer *renderer,
RenderPassCallback mainPassRecordingStart,
RenderPassCallback mainPassRecordingEnd,
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 8fc8c711c6..be6ef25feb 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -410,9 +410,9 @@ class QSGTextMaskRhiShader : public QSGMaterialRhiShader
public:
QSGTextMaskRhiShader(QFontEngine::GlyphFormat glyphFormat);
- bool updateUniformData(const RenderState &state,
+ bool updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
protected:
@@ -428,7 +428,7 @@ QSGTextMaskRhiShader::QSGTextMaskRhiShader(QFontEngine::GlyphFormat glyphFormat)
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/textmask.frag.qsb"));
}
-bool QSGTextMaskRhiShader::updateUniformData(const RenderState &state,
+bool QSGTextMaskRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
@@ -471,7 +471,7 @@ bool QSGTextMaskRhiShader::updateUniformData(const RenderState &state,
return changed;
}
-void QSGTextMaskRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void QSGTextMaskRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *)
{
Q_UNUSED(state);
@@ -498,10 +498,10 @@ public:
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/8bittextmask.frag.qsb"));
}
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
-bool QSG8BitTextMaskRhiShader::updateUniformData(const RenderState &state,
+bool QSG8BitTextMaskRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = QSGTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -532,8 +532,8 @@ public:
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/24bittextmask.frag.qsb"));
}
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps,
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
@@ -544,7 +544,7 @@ public:
// framebuffer update and blending always on... Could we do gamma correction in
// the shader for text? (but that's bad for blending?)
-bool QSG24BitTextMaskRhiShader::updateUniformData(const RenderState &state,
+bool QSG24BitTextMaskRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = QSGTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -565,7 +565,7 @@ bool QSG24BitTextMaskRhiShader::updateUniformData(const RenderState &state,
return changed;
}
-bool QSG24BitTextMaskRhiShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps,
+bool QSG24BitTextMaskRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_UNUSED(state);
@@ -596,10 +596,10 @@ public:
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/32bitcolortext.frag.qsb"));
}
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
-bool QSG32BitColorTextRhiShader::updateUniformData(const RenderState &state,
+bool QSG32BitColorTextRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = QSGTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -636,11 +636,11 @@ public:
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/styledtext.frag.qsb"));
}
- bool updateUniformData(const RenderState &state,
+ bool updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
-bool QSGStyledTextRhiShader::updateUniformData(const RenderState &state,
+bool QSGStyledTextRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = QSG8BitTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -751,15 +751,15 @@ void QSGTextMaskMaterial::updateCache(QFontEngine::GlyphFormat glyphFormat)
void *cacheKey;
if (m_rhi) {
cacheKey = m_rhi;
- // ### no idea what the QWindow is (esp. since we are not even
- // rendering at this point), and anyway is the original logic correct
- // even...
- devicePixelRatio = qGuiApp->devicePixelRatio();
+ // Get the dpr the modern way. This value retrieved via the
+ // rendercontext matches what RenderState::devicePixelRatio()
+ // exposes to the material shaders later on.
+ devicePixelRatio = m_rc->currentDevicePixelRatio();
} else {
ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
Q_ASSERT(ctx != nullptr);
cacheKey = ctx;
- devicePixelRatio = qsg_device_pixel_ratio(ctx);
+ devicePixelRatio = qsg_device_pixel_ratio(ctx); // this is technically incorrect, see other branch above
}
QTransform glyphCacheTransform = QTransform::fromScale(devicePixelRatio, devicePixelRatio);
diff --git a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp
index d1711f7524..500d4e6e95 100644
--- a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp
@@ -66,7 +66,7 @@ class SmoothTextureMaterialRhiShader : public QSGTextureMaterialRhiShader
public:
SmoothTextureMaterialRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
@@ -136,7 +136,7 @@ SmoothTextureMaterialRhiShader::SmoothTextureMaterialRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/smoothtexture.frag.qsb"));
}
-bool SmoothTextureMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+bool SmoothTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = false;
QByteArray *buf = state.uniformData();
diff --git a/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp
index 417b63dee3..5e4affbf90 100644
--- a/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp
@@ -111,7 +111,7 @@ class SmoothColorMaterialRhiShader : public QSGMaterialRhiShader
public:
SmoothColorMaterialRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
SmoothColorMaterialRhiShader::SmoothColorMaterialRhiShader()
@@ -120,7 +120,7 @@ SmoothColorMaterialRhiShader::SmoothColorMaterialRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/smoothcolor.frag.qsb"));
}
-bool SmoothColorMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *, QSGMaterial *oldMaterial)
+bool SmoothColorMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *oldMaterial)
{
bool changed = false;
QByteArray *buf = state.uniformData();
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 60a525b877..e8c3ac4abb 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -68,6 +68,7 @@ QSGDefaultRenderContext::QSGDefaultRenderContext(QSGContext *context)
, m_glAtlasManager(nullptr)
, m_rhiAtlasManager(nullptr)
, m_currentFrameCommandBuffer(nullptr)
+ , m_currentFrameRenderPass(nullptr)
{
}
@@ -199,6 +200,11 @@ void QSGDefaultRenderContext::invalidate()
emit invalidated();
}
+void QSGDefaultRenderContext::prepareSync(qreal devicePixelRatio)
+{
+ m_currentDevicePixelRatio = devicePixelRatio;
+}
+
static QBasicMutex qsg_framerender_mutex;
void QSGDefaultRenderContext::beginNextFrame(QSGRenderer *renderer,
@@ -239,6 +245,7 @@ void QSGDefaultRenderContext::beginNextRhiFrame(QSGRenderer *renderer, QRhiRende
renderer->setRenderPassRecordingCallbacks(mainPassRecordingStart, mainPassRecordingEnd, callbackUserData);
m_currentFrameCommandBuffer = cb;
+ m_currentFrameRenderPass = rp;
}
void QSGDefaultRenderContext::renderNextRhiFrame(QSGRenderer *renderer)
@@ -250,6 +257,7 @@ void QSGDefaultRenderContext::endNextRhiFrame(QSGRenderer *renderer)
{
Q_UNUSED(renderer);
m_currentFrameCommandBuffer = nullptr;
+ m_currentFrameRenderPass = nullptr;
}
/*!
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
index 79bc9dd76d..2fdb3a48dd 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
@@ -62,6 +62,7 @@ QT_BEGIN_NAMESPACE
class QRhi;
class QRhiCommandBuffer;
+class QRhiRenderPassDescriptor;
class QOpenGLContext;
class QSGMaterialShader;
class QSGMaterialRhiShader;
@@ -103,6 +104,7 @@ public:
void initialize(const QSGRenderContext::InitParams *params) override;
void invalidate() override;
+ void prepareSync(qreal devicePixelRatio) override;
void beginNextFrame(QSGRenderer *renderer,
RenderPassCallback mainPassRecordingStart,
RenderPassCallback mainPassRecordingEnd,
@@ -145,6 +147,21 @@ public:
// may be null if not in an active frame, but returning null is valid then
return m_currentFrameCommandBuffer;
}
+ QRhiRenderPassDescriptor *currentFrameRenderPass() const {
+ // may be null if not in an active frame, but returning null is valid then
+ return m_currentFrameRenderPass;
+ }
+
+ qreal currentDevicePixelRatio() const
+ {
+ // Valid starting from QQuickWindow::syncSceneGraph(). This takes the
+ // redirections, e.g. QQuickWindow::setRenderTarget(), into account.
+ // This calculation logic matches what the renderer does, so this is
+ // the same value that gets exposed in RenderState::devicePixelRatio()
+ // to material shaders. This getter is useful to perform dpr-related
+ // operations in the sync phase (in updatePaintNode()).
+ return m_currentDevicePixelRatio;
+ }
protected:
static QString fontKey(const QRawFont &font);
@@ -160,6 +177,8 @@ protected:
QSGOpenGLAtlasTexture::Manager *m_glAtlasManager;
QSGRhiAtlasTexture::Manager *m_rhiAtlasManager;
QRhiCommandBuffer *m_currentFrameCommandBuffer;
+ QRhiRenderPassDescriptor *m_currentFrameRenderPass;
+ qreal m_currentDevicePixelRatio;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultspritenode.cpp b/src/quick/scenegraph/qsgdefaultspritenode.cpp
index 4d4d9f6971..6422a252d9 100644
--- a/src/quick/scenegraph/qsgdefaultspritenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultspritenode.cpp
@@ -141,9 +141,9 @@ class SpriteMaterialRhiShader : public QSGMaterialRhiShader
public:
SpriteMaterialRhiShader();
- bool updateUniformData(const RenderState &state,
+ bool updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
@@ -153,7 +153,7 @@ SpriteMaterialRhiShader::SpriteMaterialRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/sprite.frag.qsb"));
}
-bool SpriteMaterialRhiShader::updateUniformData(const RenderState &state,
+bool SpriteMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
#ifdef QT_NO_DEBUG
@@ -186,7 +186,7 @@ bool SpriteMaterialRhiShader::updateUniformData(const RenderState &state,
return changed;
}
-void SpriteMaterialRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void SpriteMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
if (binding != 1)
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index 9121363159..e8e9f76d04 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -212,10 +212,10 @@ class QSGDistanceFieldTextMaterialRhiShader : public QSGMaterialRhiShader
public:
QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture);
- bool updateUniformData(const RenderState &state,
+ bool updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
protected:
@@ -235,7 +235,7 @@ QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(boo
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb"));
}
-bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(const RenderState &state,
+bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
@@ -291,7 +291,7 @@ bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(const RenderState
return changed;
}
-void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *)
{
Q_UNUSED(state);
@@ -432,7 +432,7 @@ class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMate
public:
DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture);
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture)
@@ -440,7 +440,7 @@ DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShad
{
}
-bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(const RenderState &state,
+bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -548,7 +548,7 @@ class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledText
public:
DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture);
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture)
@@ -564,7 +564,7 @@ DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiSh
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb"));
}
-bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(const RenderState &state,
+bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -670,7 +670,7 @@ class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyle
public:
DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture);
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture)
@@ -686,7 +686,7 @@ DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMat
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"));
}
-bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(const RenderState &state,
+bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -809,8 +809,8 @@ class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceField
public:
QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture);
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps,
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
@@ -829,7 +829,7 @@ QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTex
QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"));
}
-bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(const RenderState &state,
+bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
@@ -855,7 +855,7 @@ bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(const R
return changed;
}
-bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps,
+bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_UNUSED(state);
diff --git a/src/quick/scenegraph/qsgopengllayer.cpp b/src/quick/scenegraph/qsgopengllayer.cpp
index 8db4cba58a..ae5032231d 100644
--- a/src/quick/scenegraph/qsgopengllayer.cpp
+++ b/src/quick/scenegraph/qsgopengllayer.cpp
@@ -408,7 +408,7 @@ void QSGOpenGLLayer::grab()
m_mirrorVertical ? m_rect.bottom() : m_rect.top(),
m_mirrorHorizontal ? -m_rect.width() : m_rect.width(),
m_mirrorVertical ? -m_rect.height() : m_rect.height());
- m_renderer->setProjectionMatrixToRect(mirrored, false);
+ m_renderer->setProjectionMatrixToRect(mirrored);
m_renderer->setClearColor(Qt::transparent);
if (m_multisampling) {
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 08d1c726ab..f609055677 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -190,6 +190,7 @@ public:
QSGRenderContext *createRenderContext(QSGContext *) const override { return rc; }
void releaseSwapchain(QQuickWindow *window);
+ void handleDeviceLoss();
bool eventFilter(QObject *watched, QEvent *event) override;
@@ -435,7 +436,26 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
gl->doneCurrent();
}
- delete d->animationController;
+ d->animationController.reset();
+}
+
+void QSGGuiThreadRenderLoop::handleDeviceLoss()
+{
+ if (!rhi || !rhi->isDeviceLost())
+ return;
+
+ qWarning("Graphics device lost, cleaning up scenegraph and releasing RHI");
+
+ for (auto it = m_windows.constBegin(), itEnd = m_windows.constEnd(); it != itEnd; ++it)
+ QQuickWindowPrivate::get(it.key())->cleanupNodesOnShutdown();
+
+ rc->invalidate();
+
+ for (auto it = m_windows.constBegin(), itEnd = m_windows.constEnd(); it != itEnd; ++it)
+ releaseSwapchain(it.key());
+
+ delete rhi;
+ rhi = nullptr;
}
void QSGGuiThreadRenderLoop::releaseSwapchain(QQuickWindow *window)
@@ -488,8 +508,11 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
const bool enableRhi = rhiSupport->isRhiEnabled();
if (enableRhi && !rhi) {
- offscreenSurface = rhiSupport->maybeCreateOffscreenSurface(window);
+ if (!offscreenSurface)
+ offscreenSurface = rhiSupport->maybeCreateOffscreenSurface(window);
+
rhi = rhiSupport->createRhi(window, offscreenSurface);
+
if (rhi) {
if (rhiSupport->isProfilingRequested())
QSGRhiProfileConnection::instance()->initialize(rhi);
@@ -561,6 +584,14 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
QRhiSwapChain::Flags flags = QRhiSwapChain::UsedAsTransferSource; // may be used in a grab
+ // QQ is always premul alpha. Decide based on alphaBufferSize in
+ // requestedFormat(). (the platform plugin can override format() but
+ // what matters here is what the application wanted, hence using the
+ // requested one)
+ const bool alpha = window->requestedFormat().alphaBufferSize() > 0;
+ if (alpha)
+ flags |= QRhiSwapChain::SurfaceHasPreMulAlpha;
+
cd->swapchain = rhi->newSwapChain();
cd->depthStencilForSwapchain = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
QSize(),
@@ -568,7 +599,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
QRhiRenderBuffer::UsedWithSwapChainOnly);
cd->swapchain->setWindow(window);
cd->swapchain->setDepthStencil(cd->depthStencilForSwapchain);
- qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d", rhiSampleCount);
+ qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d. Alpha channel requested = %s",
+ rhiSampleCount, alpha ? "yes" : "no");
cd->swapchain->setSampleCount(rhiSampleCount);
cd->swapchain->setFlags(flags);
cd->rpDescForSwapchain = cd->swapchain->newCompatibleRenderPassDescriptor();
@@ -587,6 +619,24 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
i++;
}
+ // Check for context loss.
+ if (!current && !rhi && !gl->isValid()) {
+ for (auto it = m_windows.constBegin() ; it != m_windows.constEnd(); it++) {
+ QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(it.key());
+ windowPrivate->cleanupNodesOnShutdown();
+ }
+ rc->invalidate();
+ current = gl->create() && gl->makeCurrent(window);
+ if (current) {
+ QSGDefaultRenderContext::InitParams rcParams;
+ rcParams.sampleCount = qMax(1, gl->format().samples());
+ rcParams.openGLContext = gl;
+ rcParams.initialSurfacePixelSize = window->size() * window->effectiveDevicePixelRatio();
+ rcParams.maybeSurface = window;
+ rc->initialize(&rcParams);
+ }
+ }
+
if (!current)
return;
@@ -634,24 +684,34 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (previousOutputSize != effectiveOutputSize || cd->swapchainJustBecameRenderable) {
if (cd->swapchainJustBecameRenderable)
qCDebug(QSG_LOG_RENDERLOOP, "just became exposed");
- cd->swapchainJustBecameRenderable = false;
- cd->depthStencilForSwapchain->setPixelSize(effectiveOutputSize);
- cd->depthStencilForSwapchain->build();
cd->hasActiveSwapchain = cd->swapchain->buildOrResize();
+ if (!cd->hasActiveSwapchain && rhi->isDeviceLost()) {
+ handleDeviceLoss();
+ return;
+ }
+ cd->swapchainJustBecameRenderable = false;
cd->hasRenderableSwapchain = cd->hasActiveSwapchain;
- if (!cd->hasActiveSwapchain)
- qWarning("Failed to build or resize swapchain");
- else
+
+ if (cd->hasActiveSwapchain) {
+ // surface size atomicity: now that buildOrResize() succeeded,
+ // query the size that was used in there by the swapchain, and
+ // that is the size we will use while preparing the next frame.
+ effectiveOutputSize = cd->swapchain->currentPixelSize();
qCDebug(QSG_LOG_RENDERLOOP) << "rhi swapchain size" << effectiveOutputSize;
+ } else {
+ qWarning("Failed to build or resize swapchain");
+ }
}
Q_ASSERT(rhi == cd->rhi);
- QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain);
+ // ### the flag should only be set when the app requests it, but there's no way to do that right now
+ QRhi::BeginFrameFlags frameFlags = QRhi::ExternalContentsInPass;
+ QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain, frameFlags);
if (frameResult != QRhi::FrameOpSuccess) {
if (frameResult == QRhi::FrameOpDeviceLost)
- qWarning("Device lost");
+ handleDeviceLoss();
else if (frameResult == QRhi::FrameOpError)
qWarning("Failed to start frame");
// out of date is not worth warning about - it may happen even during resizing on some platforms
@@ -690,7 +750,13 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
QRhi::EndFrameFlags flags = 0;
if (!needsPresent)
flags |= QRhi::SkipPresent;
- rhi->endFrame(cd->swapchain, flags);
+ QRhi::FrameOpResult frameResult = rhi->endFrame(cd->swapchain, flags);
+ if (frameResult != QRhi::FrameOpSuccess) {
+ if (frameResult == QRhi::FrameOpDeviceLost)
+ handleDeviceLoss();
+ else if (frameResult == QRhi::FrameOpError)
+ qWarning("Failed to end frame");
+ }
} else if (needsPresent) {
if (!cd->customRenderStage || !cd->customRenderStage->swap())
gl->swapBuffers(window);
diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
index 28fc10e413..53b6fe117f 100644
--- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
@@ -182,7 +182,9 @@ void QSGRhiDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField> &gly
for (int i = 0; i < glyphs.size(); ++i) {
TextureInfo *texInfo = m_glyphsTexture.value(glyphs.at(i).glyph());
if (!texInfo->uploads.isEmpty()) {
- m_resourceUpdates->uploadTexture(texInfo->texture, texInfo->uploads);
+ QRhiTextureUploadDescription desc;
+ desc.setEntries(texInfo->uploads.cbegin(), texInfo->uploads.cend());
+ m_resourceUpdates->uploadTexture(texInfo->texture, desc);
texInfo->uploads.clear();
}
}
diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h
index ddd3d92ba7..d43b0aa5d4 100644
--- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h
@@ -88,7 +88,7 @@ private:
QRect allocatedArea;
QDistanceField image;
int padding = -1;
- QVector<QRhiTextureUploadEntry> uploads;
+ QVarLengthArray<QRhiTextureUploadEntry, 16> uploads;
TextureInfo(const QRect &preallocRect = QRect()) : texture(nullptr), allocatedArea(preallocRect) { }
};
diff --git a/src/quick/scenegraph/qsgrhilayer.cpp b/src/quick/scenegraph/qsgrhilayer.cpp
index 80ca40d50a..757410eded 100644
--- a/src/quick/scenegraph/qsgrhilayer.cpp
+++ b/src/quick/scenegraph/qsgrhilayer.cpp
@@ -388,7 +388,10 @@ void QSGRhiLayer::grab()
m_mirrorHorizontal ? -m_rect.width() : m_rect.width(),
m_mirrorVertical ? m_rect.height() : -m_rect.height());
}
- m_renderer->setProjectionMatrixToRect(mirrored, !m_rhi->isYUpInNDC());
+ QSGAbstractRenderer::MatrixTransformFlags matrixFlags = 0;
+ if (!m_rhi->isYUpInNDC())
+ matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY;
+ m_renderer->setProjectionMatrixToRect(mirrored, matrixFlags);
m_renderer->setClearColor(Qt::transparent);
m_renderer->setRenderTarget(m_rt);
m_renderer->setCommandBuffer(m_context->currentFrameCommandBuffer());
diff --git a/src/quick/scenegraph/qsgrhishadereffectnode.cpp b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
index fe9cecb51b..6f6544548c 100644
--- a/src/quick/scenegraph/qsgrhishadereffectnode.cpp
+++ b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
@@ -211,9 +211,9 @@ class QSGRhiShaderEffectMaterialShader : public QSGMaterialRhiShader
public:
QSGRhiShaderEffectMaterialShader(const QSGRhiShaderEffectMaterial *material);
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
QSGRhiShaderEffectMaterialShader::QSGRhiShaderEffectMaterialShader(const QSGRhiShaderEffectMaterial *material)
@@ -228,7 +228,7 @@ static inline QColor qsg_premultiply_color(const QColor &c)
return QColor::fromRgbF(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF());
}
-bool QSGRhiShaderEffectMaterialShader::updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+bool QSGRhiShaderEffectMaterialShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_UNUSED(oldMaterial);
QSGRhiShaderEffectMaterial *mat = static_cast<QSGRhiShaderEffectMaterial *>(newMaterial);
@@ -381,7 +381,7 @@ bool QSGRhiShaderEffectMaterialShader::updateUniformData(const RenderState &stat
return changed;
}
-void QSGRhiShaderEffectMaterialShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void QSGRhiShaderEffectMaterialShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_UNUSED(oldMaterial);
@@ -426,7 +426,7 @@ void QSGRhiShaderEffectMaterialShader::updateSampledImage(const RenderState &sta
*texture = mat->m_dummyTexture;
}
-bool QSGRhiShaderEffectMaterialShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps,
+bool QSGRhiShaderEffectMaterialShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_UNUSED(state);
diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp
index a92b6b0c84..12c6742342 100644
--- a/src/quick/scenegraph/qsgrhisupport.cpp
+++ b/src/quick/scenegraph/qsgrhisupport.cpp
@@ -101,7 +101,8 @@ QSGRhiSupport::QSGRhiSupport()
m_enableRhi(false),
m_debugLayer(false),
m_profile(false),
- m_shaderEffectDebug(false)
+ m_shaderEffectDebug(false),
+ m_preferSoftwareRenderer(false)
{
}
@@ -140,7 +141,7 @@ void QSGRhiSupport::applySettings()
}
} else {
// check env.vars., fall back to platform-specific defaults when backend is not set
- m_enableRhi = qEnvironmentVariableIntValue("QSG_RHI");
+ m_enableRhi = uint(qEnvironmentVariableIntValue("QSG_RHI"));
const QByteArray rhiBackend = qgetenv("QSG_RHI_BACKEND");
if (rhiBackend == QByteArrayLiteral("gl")
|| rhiBackend == QByteArrayLiteral("gles2")
@@ -171,12 +172,18 @@ void QSGRhiSupport::applySettings()
return;
// validation layers (Vulkan) or debug layer (D3D)
- m_debugLayer = qEnvironmentVariableIntValue("QSG_RHI_DEBUG_LAYER");
+ m_debugLayer = uint(qEnvironmentVariableIntValue("QSG_RHI_DEBUG_LAYER"));
// EnableProfiling + DebugMarkers
- m_profile = qEnvironmentVariableIntValue("QSG_RHI_PROFILE");
+ m_profile = uint(qEnvironmentVariableIntValue("QSG_RHI_PROFILE"));
- m_shaderEffectDebug = qEnvironmentVariableIntValue("QSG_RHI_SHADEREFFECT_DEBUG");
+ m_shaderEffectDebug = uint(qEnvironmentVariableIntValue("QSG_RHI_SHADEREFFECT_DEBUG"));
+
+ m_preferSoftwareRenderer = uint(qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER"));
+
+ m_killDeviceFrameCount = qEnvironmentVariableIntValue("QSG_RHI_SIMULATE_DEVICE_LOSS");
+ if (m_killDeviceFrameCount > 0 && m_rhiBackend == QRhi::D3D11)
+ qDebug("Graphics device will be reset every %d frames", m_killDeviceFrameCount);
const char *backendName = "unknown";
switch (m_rhiBackend) {
@@ -201,6 +208,8 @@ void QSGRhiSupport::applySettings()
qCDebug(QSG_LOG_INFO,
"Using QRhi with backend %s\n graphics API debug/validation layers: %d\n QRhi profiling and debug markers: %d",
backendName, m_debugLayer, m_profile);
+ if (m_preferSoftwareRenderer)
+ qCDebug(QSG_LOG_INFO, "Prioritizing software renderers");
}
QSGRhiSupport *QSGRhiSupport::staticInst()
@@ -279,12 +288,16 @@ QSurface::SurfaceType QSGRhiSupport::windowSurfaceType() const
}
#if QT_CONFIG(vulkan)
-static const void *qsgrhi_vk_rifResource(QSGRendererInterface::Resource res, const QRhiNativeHandles *nat,
- const QRhiNativeHandles *cbNat)
+static const void *qsgrhi_vk_rifResource(QSGRendererInterface::Resource res,
+ const QRhiNativeHandles *nat,
+ const QRhiNativeHandles *cbNat,
+ const QRhiNativeHandles *rpNat)
{
const QRhiVulkanNativeHandles *vknat = static_cast<const QRhiVulkanNativeHandles *>(nat);
const QRhiVulkanCommandBufferNativeHandles *maybeVkCbNat =
static_cast<const QRhiVulkanCommandBufferNativeHandles *>(cbNat);
+ const QRhiVulkanRenderPassNativeHandles *maybeVkRpNat =
+ static_cast<const QRhiVulkanRenderPassNativeHandles *>(rpNat);
switch (res) {
case QSGRendererInterface::DeviceResource:
@@ -298,6 +311,11 @@ static const void *qsgrhi_vk_rifResource(QSGRendererInterface::Resource res, con
return nullptr;
case QSGRendererInterface::PhysicalDeviceResource:
return &vknat->physDev;
+ case QSGRendererInterface::RenderPassResource:
+ if (maybeVkRpNat)
+ return &maybeVkRpNat->renderPass;
+ else
+ return nullptr;
default:
return nullptr;
}
@@ -376,7 +394,10 @@ const void *QSGRhiSupport::rifResource(QSGRendererInterface::Resource res, const
case QRhi::Vulkan:
{
QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
- return qsgrhi_vk_rifResource(res, nat, cb ? cb->nativeHandles() : nullptr);
+ QRhiRenderPassDescriptor *rp = rc->currentFrameRenderPass();
+ return qsgrhi_vk_rifResource(res, nat,
+ cb ? cb->nativeHandles() : nullptr,
+ rp ? rp->nativeHandles() : nullptr);
}
#endif
#if QT_CONFIG(opengl)
@@ -447,6 +468,8 @@ QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurf
QRhi::Flags flags = 0;
if (isProfilingRequested())
flags |= QRhi::EnableProfiling | QRhi::EnableDebugMarkers;
+ if (isSoftwareRendererRequested())
+ flags |= QRhi::PreferSoftwareRenderer;
QRhi::Implementation backend = rhiBackend();
if (backend == QRhi::Null) {
@@ -477,6 +500,10 @@ QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurf
if (backend == QRhi::D3D11) {
QRhiD3D11InitParams rhiParams;
rhiParams.enableDebugLayer = isDebugLayerRequested();
+ if (m_killDeviceFrameCount > 0) {
+ rhiParams.framesUntilKillingDeviceViaTdr = m_killDeviceFrameCount;
+ rhiParams.repeatDeviceKill = true;
+ }
rhi = QRhi::create(backend, &rhiParams, flags);
}
#endif
diff --git a/src/quick/scenegraph/qsgrhisupport_p.h b/src/quick/scenegraph/qsgrhisupport_p.h
index f2d5837bba..d008ecd0af 100644
--- a/src/quick/scenegraph/qsgrhisupport_p.h
+++ b/src/quick/scenegraph/qsgrhisupport_p.h
@@ -114,6 +114,7 @@ public:
bool isDebugLayerRequested() const { return m_debugLayer; }
bool isProfilingRequested() const { return m_profile; }
bool isShaderEffectDebuggingRequested() const { return m_shaderEffectDebug; }
+ bool isSoftwareRendererRequested() const { return m_preferSoftwareRenderer; }
QSurface::SurfaceType windowSurfaceType() const;
@@ -138,11 +139,13 @@ private:
uint rhi : 1;
} m_requested;
QRhi::Implementation m_rhiBackend = QRhi::Null;
+ int m_killDeviceFrameCount;
uint m_set : 1;
uint m_enableRhi : 1;
uint m_debugLayer : 1;
uint m_profile : 1;
uint m_shaderEffectDebug : 1;
+ uint m_preferSoftwareRenderer : 1;
};
// Sends QRhi resource statistics over a QTcpSocket. To be initialized by the
diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
index 99761302e2..d0108bc56e 100644
--- a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
+++ b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
@@ -223,7 +223,9 @@ void QSGRhiTextureGlyphCache::endFillTexture()
if (!m_resourceUpdates)
m_resourceUpdates = m_rhi->nextResourceUpdateBatch();
- m_resourceUpdates->uploadTexture(m_texture, m_uploads);
+ QRhiTextureUploadDescription desc;
+ desc.setEntries(m_uploads.cbegin(), m_uploads.cend());
+ m_resourceUpdates->uploadTexture(m_texture, desc);
m_uploads.clear();
}
diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache_p.h b/src/quick/scenegraph/qsgrhitextureglyphcache_p.h
index 75d82de90d..a7374d91a4 100644
--- a/src/quick/scenegraph/qsgrhitextureglyphcache_p.h
+++ b/src/quick/scenegraph/qsgrhitextureglyphcache_p.h
@@ -90,7 +90,7 @@ private:
QRhiTexture *m_texture = nullptr;
QSize m_size;
bool m_bgra = false;
- QVector<QRhiTextureUploadEntry> m_uploads;
+ QVarLengthArray<QRhiTextureUploadEntry, 16> m_uploads;
QSet<QRhiTexture *> m_pendingDispose;
};
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 9e34a2b201..86d9590863 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -199,7 +199,7 @@ public:
WMSyncEvent(QQuickWindow *c, bool inExpose, bool force)
: WMWindowEvent(c, WM_RequestSync)
, size(c->size())
- , dpr(c->effectiveDevicePixelRatio())
+ , dpr(float(c->effectiveDevicePixelRatio()))
, syncInExpose(inExpose)
, forceRenderPass(force)
{}
@@ -306,8 +306,7 @@ public:
delete offscreenSurface;
}
- void invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *backupSurface);
- void initializeOpenGL();
+ void invalidateGraphics(QQuickWindow *window, bool inDestructor, QOffscreenSurface *backupSurface);
bool event(QEvent *) override;
void run() override;
@@ -340,6 +339,9 @@ public:
ExposeRequest = 0x04 | RepaintRequest | SyncRequest
};
+ void ensureRhi();
+ void handleDeviceLoss();
+
QSGThreadedRenderLoop *wm;
QOpenGLContext *gl;
bool enableRhi;
@@ -419,9 +421,9 @@ bool QSGRenderThread::event(QEvent *e)
WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e);
if (!window || wme->inDestructor) {
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- setting exit flag and invalidating OpenGL");
- invalidateOpenGL(wme->window, wme->inDestructor, wme->needsFallback ? offscreenSurface : nullptr);
+ invalidateGraphics(wme->window, wme->inDestructor, wme->needsFallback ? offscreenSurface : nullptr);
active = gl || rhi;
- Q_ASSERT_X(!wme->inDestructor || !active, "QSGRenderThread::invalidateOpenGL()", "Thread's active state is not set to false when shutting down");
+ Q_ASSERT_X(!wme->inDestructor || !active, "QSGRenderThread::invalidateGraphics()", "Thread's active state is not set to false when shutting down");
if (sleeping)
stopEventProcessing = true;
} else {
@@ -512,9 +514,9 @@ bool QSGRenderThread::event(QEvent *e)
return QThread::event(e);
}
-void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *fallback)
+void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor, QOffscreenSurface *fallback)
{
- qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "invalidateOpenGL()");
+ qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "invalidateGraphics()");
if (!gl && !rhi)
return;
@@ -562,7 +564,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor,
QCoreApplication::processEvents();
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
if (inDestructor)
- delete dd->animationController;
+ dd->animationController.reset();
if (current && gl)
gl->doneCurrent();
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- invalidating scene graph");
@@ -615,7 +617,7 @@ void QSGRenderThread::sync(bool inExpose, bool inGrab)
QSGDefaultRenderContext::InitParams rcParams;
rcParams.sampleCount = qMax(1, gl->format().samples());
rcParams.openGLContext = gl;
- rcParams.initialSurfacePixelSize = windowSize * dpr;
+ rcParams.initialSurfacePixelSize = windowSize * qreal(dpr);
rcParams.maybeSurface = window;
sgrc->initialize(&rcParams);
}
@@ -658,6 +660,19 @@ void QSGRenderThread::sync(bool inExpose, bool inGrab)
}
}
+void QSGRenderThread::handleDeviceLoss()
+{
+ if (!rhi || !rhi->isDeviceLost())
+ return;
+
+ qWarning("Graphics device lost, cleaning up scenegraph and releasing RHI");
+ QQuickWindowPrivate::get(window)->cleanupNodesOnShutdown();
+ sgrc->invalidate();
+ wm->releaseSwapchain(window);
+ delete rhi;
+ rhi = nullptr;
+}
+
void QSGRenderThread::syncAndRender(QImage *grabImage)
{
bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
@@ -699,30 +714,35 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
if (previousOutputSize != effectiveOutputSize || cd->swapchainJustBecameRenderable) {
if (cd->swapchainJustBecameRenderable)
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "just became exposed");
- cd->swapchainJustBecameRenderable = false;
- cd->depthStencilForSwapchain->setPixelSize(effectiveOutputSize);
- cd->depthStencilForSwapchain->build();
cd->hasActiveSwapchain = cd->swapchain->buildOrResize();
+ if (!cd->hasActiveSwapchain && rhi->isDeviceLost()) {
+ handleDeviceLoss();
+ QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
+ return;
+ }
+ cd->swapchainJustBecameRenderable = false;
cd->hasRenderableSwapchain = cd->hasActiveSwapchain;
+
if (!cd->hasActiveSwapchain)
qWarning("Failed to build or resize swapchain");
else
- qCDebug(QSG_LOG_RENDERLOOP) << "rhi swapchain size" << effectiveOutputSize;
+ qCDebug(QSG_LOG_RENDERLOOP) << "rhi swapchain size" << cd->swapchain->currentPixelSize();
}
Q_ASSERT(rhi == cd->rhi);
- QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain);
+ // ### the flag should only be set when the app requests it, but there's no way to do that right now
+ QRhi::BeginFrameFlags frameFlags = QRhi::ExternalContentsInPass;
+ QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain, frameFlags);
if (frameResult != QRhi::FrameOpSuccess) {
if (frameResult == QRhi::FrameOpDeviceLost)
- qWarning("Device lost");
+ handleDeviceLoss();
else if (frameResult == QRhi::FrameOpError)
qWarning("Failed to start frame");
// try again later
if (frameResult == QRhi::FrameOpDeviceLost || frameResult == QRhi::FrameOpSwapChainOutOfDate)
QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
-
// Before returning we need to ensure the same wake up logic that
// would have happened if beginFrame() had suceeded.
if (exposeRequested) {
@@ -787,8 +807,9 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
}
}
if (current) {
+ const QSize outputSize = rhi ? cd->swapchain->currentPixelSize() : windowSize;
- d->renderSceneGraph(windowSize);
+ d->renderSceneGraph(outputSize);
if (profileFrames)
renderTime = threadTimer.nsecsElapsed();
@@ -808,7 +829,15 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
QRhi::EndFrameFlags flags = 0;
if (grabImage)
flags |= QRhi::SkipPresent;
- rhi->endFrame(cd->swapchain, flags);
+ QRhi::FrameOpResult frameResult = rhi->endFrame(cd->swapchain, flags);
+ if (frameResult != QRhi::FrameOpSuccess) {
+ if (frameResult == QRhi::FrameOpDeviceLost)
+ handleDeviceLoss();
+ else if (frameResult == QRhi::FrameOpError)
+ qWarning("Failed to end frame");
+ if (frameResult == QRhi::FrameOpDeviceLost || frameResult == QRhi::FrameOpSwapChainOutOfDate)
+ QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
+ }
} else {
if (!cd->customRenderStage || !cd->customRenderStage->swap())
gl->swapBuffers(window);
@@ -882,6 +911,57 @@ void QSGRenderThread::processEventsAndWaitForMore()
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "--- done processEventsAndWaitForMore()");
}
+void QSGRenderThread::ensureRhi()
+{
+ if (!rhi) {
+ QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
+ rhi = rhiSupport->createRhi(window, offscreenSurface);
+ if (rhi) {
+ rhiSampleCount = rhiSupport->chooseSampleCountForWindowWithRhi(window, rhi);
+ if (rhiSupport->isProfilingRequested())
+ QSGRhiProfileConnection::instance()->initialize(rhi); // ### this breaks down with multiple windows
+ } else {
+ qWarning("Failed to create QRhi on the render thread; scenegraph is not functional");
+ return;
+ }
+ }
+ if (!sgrc->rhi() && windowSize.width() > 0 && windowSize.height() > 0) {
+ rhi->makeThreadLocalNativeContextCurrent();
+ QSGDefaultRenderContext::InitParams rcParams;
+ rcParams.rhi = rhi;
+ rcParams.sampleCount = rhiSampleCount;
+ rcParams.openGLContext = nullptr;
+ rcParams.initialSurfacePixelSize = windowSize * qreal(dpr);
+ rcParams.maybeSurface = window;
+ sgrc->initialize(&rcParams);
+ }
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
+ if (rhi && !cd->swapchain) {
+ cd->rhi = rhi;
+ QRhiSwapChain::Flags flags = QRhiSwapChain::UsedAsTransferSource; // may be used in a grab
+ // QQ is always premul alpha. Decide based on alphaBufferSize in
+ // requestedFormat(). (the platform plugin can override format() but
+ // what matters here is what the application wanted, hence using the
+ // requested one)
+ const bool alpha = window->requestedFormat().alphaBufferSize() > 0;
+ if (alpha)
+ flags |= QRhiSwapChain::SurfaceHasPreMulAlpha;
+ cd->swapchain = rhi->newSwapChain();
+ cd->depthStencilForSwapchain = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(),
+ rhiSampleCount,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ cd->swapchain->setWindow(window);
+ cd->swapchain->setDepthStencil(cd->depthStencilForSwapchain);
+ qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d. Alpha channel requested = %s.",
+ rhiSampleCount, alpha ? "yes" : "no");
+ cd->swapchain->setSampleCount(rhiSampleCount);
+ cd->swapchain->setFlags(flags);
+ cd->rpDescForSwapchain = cd->swapchain->newCompatibleRenderPassDescriptor();
+ cd->swapchain->setRenderPassDescriptor(cd->rpDescForSwapchain);
+ }
+}
+
void QSGRenderThread::run()
{
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "run()");
@@ -897,55 +977,20 @@ void QSGRenderThread::run()
if (window) {
if (enableRhi) {
- if (!rhi) {
- QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
- rhi = rhiSupport->createRhi(window, offscreenSurface);
- if (rhi) {
- rhiSampleCount = rhiSupport->chooseSampleCountForWindowWithRhi(window, rhi);
- if (rhiSupport->isProfilingRequested())
- QSGRhiProfileConnection::instance()->initialize(rhi); // ### this breaks down with multiple windows
- } else {
- qWarning("Failed to create QRhi on the render thread; scenegraph is not functional");
- }
- }
- if (!sgrc->rhi() && windowSize.width() > 0 && windowSize.height() > 0) {
- rhi->makeThreadLocalNativeContextCurrent();
- QSGDefaultRenderContext::InitParams rcParams;
- rcParams.rhi = rhi;
- rcParams.sampleCount = rhiSampleCount;
- rcParams.openGLContext = gl;
- rcParams.initialSurfacePixelSize = windowSize * dpr;
- rcParams.maybeSurface = window;
- sgrc->initialize(&rcParams);
- }
- QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
- if (rhi && !cd->swapchain) {
- cd->rhi = rhi;
- QRhiSwapChain::Flags flags = QRhiSwapChain::UsedAsTransferSource; // may be used in a grab
- cd->swapchain = rhi->newSwapChain();
- cd->depthStencilForSwapchain = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
- QSize(),
- rhiSampleCount,
- QRhiRenderBuffer::UsedWithSwapChainOnly);
- cd->swapchain->setWindow(window);
- cd->swapchain->setDepthStencil(cd->depthStencilForSwapchain);
- qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d", rhiSampleCount);
- cd->swapchain->setSampleCount(rhiSampleCount);
- cd->swapchain->setFlags(flags);
- cd->rpDescForSwapchain = cd->swapchain->newCompatibleRenderPassDescriptor();
- cd->swapchain->setRenderPassDescriptor(cd->rpDescForSwapchain);
- }
+ ensureRhi();
+ if (rhi)
+ syncAndRender();
} else {
if (!sgrc->openglContext() && windowSize.width() > 0 && windowSize.height() > 0 && gl->makeCurrent(window)) {
QSGDefaultRenderContext::InitParams rcParams;
rcParams.sampleCount = qMax(1, gl->format().samples());
rcParams.openGLContext = gl;
- rcParams.initialSurfacePixelSize = windowSize * dpr;
+ rcParams.initialSurfacePixelSize = windowSize * qreal(dpr);
rcParams.maybeSurface = window;
sgrc->initialize(&rcParams);
}
+ syncAndRender();
}
- syncAndRender();
}
processEvents();
@@ -1257,7 +1302,8 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
}
}
- QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController;
+ QQuickAnimatorController *controller
+ = QQuickWindowPrivate::get(w->window)->animationController.get();
if (controller->thread() != w->thread)
controller->moveToThread(w->thread);
@@ -1352,6 +1398,8 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w)
return;
QThread *current = QThread::currentThread();
+ if (current == w->thread && w->thread->rhi && w->thread->rhi->isDeviceLost())
+ return;
if (current != QCoreApplication::instance()->thread() && (current != w->thread || !m_lockedForSync)) {
qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()";
return;
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 220c70c299..5b48b86568 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -269,7 +269,7 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window)
m_gl->doneCurrent();
}
- delete d->animationController;
+ d->animationController.reset();
}
bool QSGWindowsRenderLoop::anyoneShowing() const
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index c345f3b16d..56d97226fb 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -94,7 +94,6 @@ qtConfig(opengl(es1|es2)?) {
# rhi, still tied to OpenGL-enabled Qt builds for now
HEADERS += \
- $$PWD/qsgrhisupport_p.h \
$$PWD/qsgrhitextureglyphcache_p.h \
$$PWD/util/qsgrhiatlastexture_p.h \
$$PWD/qsgrhilayer_p.h \
@@ -102,7 +101,6 @@ qtConfig(opengl(es1|es2)?) {
$$PWD/qsgrhidistancefieldglyphcache_p.h
SOURCES += \
- $$PWD/qsgrhisupport.cpp \
$$PWD/qsgrhitextureglyphcache.cpp \
$$PWD/qsgrhilayer.cpp \
$$PWD/qsgrhishadereffectnode.cpp \
@@ -118,7 +116,8 @@ HEADERS += \
$$PWD/qsgbasicinternalrectanglenode_p.h \
$$PWD/qsgbasicinternalimagenode_p.h \
$$PWD/qsgbasicglyphnode_p.h \
- $$PWD/qsgrenderloop_p.h
+ $$PWD/qsgrenderloop_p.h \
+ $$PWD/qsgrhisupport_p.h
SOURCES += \
$$PWD/qsgadaptationlayer.cpp \
@@ -127,7 +126,8 @@ SOURCES += \
$$PWD/qsgbasicinternalrectanglenode.cpp \
$$PWD/qsgbasicinternalimagenode.cpp \
$$PWD/qsgbasicglyphnode.cpp \
- $$PWD/qsgrenderloop.cpp
+ $$PWD/qsgrenderloop.cpp \
+ $$PWD/qsgrhisupport.cpp
qtConfig(opengl(es1|es2)?) {
SOURCES += \
diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
index f121d2a9e2..87941bf31a 100644
--- a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
+++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
@@ -121,7 +121,7 @@ class FlatColorMaterialRhiShader : public QSGMaterialRhiShader
public:
FlatColorMaterialRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
FlatColorMaterialRhiShader::FlatColorMaterialRhiShader()
@@ -130,7 +130,7 @@ FlatColorMaterialRhiShader::FlatColorMaterialRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/flatcolor.frag.qsb"));
}
-bool FlatColorMaterialRhiShader::updateUniformData(const RenderState &state,
+bool FlatColorMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial,
QSGMaterial *oldMaterial)
{
diff --git a/src/quick/scenegraph/util/qsgrhiatlastexture.cpp b/src/quick/scenegraph/util/qsgrhiatlastexture.cpp
index 665e9bb412..3dc1f5f526 100644
--- a/src/quick/scenegraph/util/qsgrhiatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgrhiatlastexture.cpp
@@ -295,8 +295,7 @@ void Atlas::enqueueTextureUpload(TextureBase *t, QRhiResourceUpdateBatch *resour
const int tmpBitsSize = tmpBits.size() * 4;
const quint32 *src = reinterpret_cast<const quint32 *>(image.constBits());
quint32 *dst = tmpBits.data();
- QVector<QRhiTextureUploadEntry> entries;
- entries.reserve(5);
+ QVarLengthArray<QRhiTextureUploadEntry, 5> entries;
// top row, padding corners
dst[0] = src[0];
@@ -361,7 +360,9 @@ void Atlas::enqueueTextureUpload(TextureBase *t, QRhiResourceUpdateBatch *resour
entries.append(QRhiTextureUploadEntry(0, 0, subresDesc));
}
- resourceUpdates->uploadTexture(m_texture, QRhiTextureUploadDescription(entries));
+ QRhiTextureUploadDescription desc;
+ desc.setEntries(entries.cbegin(), entries.cend());
+ resourceUpdates->uploadTexture(m_texture, desc);
const QSize textureSize = t->textureSize();
if (textureSize.width() > m_atlas_transient_image_threshold || textureSize.height() > m_atlas_transient_image_threshold)
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
index df4e5cfde2..67b8748119 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial.cpp
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
@@ -125,7 +125,7 @@ QSGOpaqueTextureMaterialRhiShader::QSGOpaqueTextureMaterialRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/opaquetexture.frag.qsb"));
}
-bool QSGOpaqueTextureMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *, QSGMaterial *)
+bool QSGOpaqueTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *)
{
bool changed = false;
QByteArray *buf = state.uniformData();
@@ -139,7 +139,7 @@ bool QSGOpaqueTextureMaterialRhiShader::updateUniformData(const RenderState &sta
return changed;
}
-void QSGOpaqueTextureMaterialRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void QSGOpaqueTextureMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
if (binding != 1)
@@ -473,7 +473,7 @@ QSGTextureMaterialRhiShader::QSGTextureMaterialRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/texture.frag.qsb"));
}
-bool QSGTextureMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+bool QSGTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
bool changed = false;
QByteArray *buf = state.uniformData();
diff --git a/src/quick/scenegraph/util/qsgtexturematerial_p.h b/src/quick/scenegraph/util/qsgtexturematerial_p.h
index 7ef17af526..d1ef7d1d7f 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial_p.h
+++ b/src/quick/scenegraph/util/qsgtexturematerial_p.h
@@ -75,8 +75,8 @@ class Q_QUICK_PRIVATE_EXPORT QSGOpaqueTextureMaterialRhiShader : public QSGMater
public:
QSGOpaqueTextureMaterialRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
class QSGTextureMaterialShader : public QSGOpaqueTextureMaterialShader
@@ -96,7 +96,7 @@ class QSGTextureMaterialRhiShader : public QSGOpaqueTextureMaterialRhiShader
public:
QSGTextureMaterialRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
index 23f57141a6..c27dd7d1f0 100644
--- a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
@@ -100,7 +100,7 @@ class QSGVertexColorMaterialRhiShader : public QSGMaterialRhiShader
public:
QSGVertexColorMaterialRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
};
QSGVertexColorMaterialRhiShader::QSGVertexColorMaterialRhiShader()
@@ -109,7 +109,7 @@ QSGVertexColorMaterialRhiShader::QSGVertexColorMaterialRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/vertexcolor.frag.qsb"));
}
-bool QSGVertexColorMaterialRhiShader::updateUniformData(const RenderState &state,
+bool QSGVertexColorMaterialRhiShader::updateUniformData(RenderState &state,
QSGMaterial * /*newEffect*/,
QSGMaterial * /*oldEffect*/)
{
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 588088b03a..5e9722e6b4 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -2636,7 +2636,7 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
for (int j = 0; j < targets.count(); ++j) {
QQuickStateAction myAction;
QString errorMessage;
- const QString propertyName = props.at(i);
+ const QString &propertyName = props.at(i);
myAction.property = d->createProperty(targets.at(j), propertyName, this, &errorMessage);
if (myAction.property.isValid()) {
if (usingDefaultProperties)
diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h
index 746cb938bd..45f1635c91 100644
--- a/src/quick/util/qquickanimation_p.h
+++ b/src/quick/util/qquickanimation_p.h
@@ -80,6 +80,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimation : public QObject, public QQ
Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopCountChanged)
Q_CLASSINFO("DefaultMethod", "start()")
+ QML_NAMED_ELEMENT(Animation)
+ QML_UNCREATABLE("Animation is an abstract class")
+
public:
enum ThreadingModel {
GuiThread,
@@ -165,6 +168,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPauseAnimation : public QQuickAbstractAnimati
Q_DECLARE_PRIVATE(QQuickPauseAnimation)
Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ QML_NAMED_ELEMENT(PauseAnimation)
public:
QQuickPauseAnimation(QObject *parent=nullptr);
@@ -191,6 +195,7 @@ class QQuickScriptAction : public QQuickAbstractAnimation
Q_PROPERTY(QQmlScriptString script READ script WRITE setScript)
Q_PROPERTY(QString scriptName READ stateChangeScriptName WRITE setStateChangeScriptName)
+ QML_NAMED_ELEMENT(ScriptAction)
public:
QQuickScriptAction(QObject *parent=nullptr);
@@ -221,6 +226,7 @@ class QQuickPropertyAction : public QQuickAbstractAnimation
Q_PROPERTY(QQmlListProperty<QObject> targets READ targets)
Q_PROPERTY(QQmlListProperty<QObject> exclude READ exclude)
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+ QML_NAMED_ELEMENT(PropertyAction)
public:
QQuickPropertyAction(QObject *parent=nullptr);
@@ -269,6 +275,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPropertyAnimation : public QQuickAbstractAnim
Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
Q_PROPERTY(QQmlListProperty<QObject> targets READ targets)
Q_PROPERTY(QQmlListProperty<QObject> exclude READ exclude)
+ QML_NAMED_ELEMENT(PropertyAnimation)
public:
QQuickPropertyAnimation(QObject *parent=nullptr);
@@ -324,6 +331,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickColorAnimation : public QQuickPropertyAnimati
Q_DECLARE_PRIVATE(QQuickPropertyAnimation)
Q_PROPERTY(QColor from READ from WRITE setFrom)
Q_PROPERTY(QColor to READ to WRITE setTo)
+ QML_NAMED_ELEMENT(ColorAnimation)
public:
QQuickColorAnimation(QObject *parent=nullptr);
@@ -343,6 +351,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickNumberAnimation : public QQuickPropertyAnimat
Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged)
Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged)
+ QML_NAMED_ELEMENT(NumberAnimation)
public:
QQuickNumberAnimation(QObject *parent=nullptr);
@@ -368,6 +377,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickVector3dAnimation : public QQuickPropertyAnim
Q_PROPERTY(QVector3D from READ from WRITE setFrom NOTIFY fromChanged)
Q_PROPERTY(QVector3D to READ to WRITE setTo NOTIFY toChanged)
+ QML_NAMED_ELEMENT(Vector3dAnimation)
public:
QQuickVector3dAnimation(QObject *parent=nullptr);
@@ -389,6 +399,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimation : public QQuickPropertyAnim
Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged)
Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged)
Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+ QML_NAMED_ELEMENT(RotationAnimation)
public:
QQuickRotationAnimation(QObject *parent=nullptr);
@@ -433,6 +444,7 @@ class QQuickSequentialAnimation : public QQuickAnimationGroup
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickAnimationGroup)
+ QML_NAMED_ELEMENT(SequentialAnimation)
public:
QQuickSequentialAnimation(QObject *parent=nullptr);
@@ -450,6 +462,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickParallelAnimation : public QQuickAnimationGro
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickAnimationGroup)
+ QML_NAMED_ELEMENT(ParallelAnimation)
public:
QQuickParallelAnimation(QObject *parent=nullptr);
diff --git a/src/quick/util/qquickanimationcontroller_p.h b/src/quick/util/qquickanimationcontroller_p.h
index d9ce377060..da6df6038a 100644
--- a/src/quick/util/qquickanimationcontroller_p.h
+++ b/src/quick/util/qquickanimationcontroller_p.h
@@ -64,6 +64,7 @@ class Q_AUTOTEST_EXPORT QQuickAnimationController : public QObject, public QQmlP
Q_DECLARE_PRIVATE(QQuickAnimationController)
Q_CLASSINFO("DefaultProperty", "animation")
+ QML_NAMED_ELEMENT(AnimationController)
Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
Q_PROPERTY(QQuickAbstractAnimation *animation READ animation WRITE setAnimation NOTIFY animationChanged)
diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h
index 511cecda7f..9f7aaafcb0 100644
--- a/src/quick/util/qquickanimator_p.h
+++ b/src/quick/util/qquickanimator_p.h
@@ -69,6 +69,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAnimator : public QQuickAbstractAnimation
Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged)
Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged)
+ QML_NAMED_ELEMENT(Animator)
+ QML_ADDED_IN_MINOR_VERSION(2)
+ QML_UNCREATABLE("Animator is an abstract class")
+
public:
QQuickItem *targetItem() const;
void setTargetItem(QQuickItem *target);
@@ -109,6 +113,8 @@ class QQuickScaleAnimatorPrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimator : public QQuickAnimator
{
Q_OBJECT
+ QML_NAMED_ELEMENT(ScaleAnimator)
+ QML_ADDED_IN_MINOR_VERSION(2)
public:
QQuickScaleAnimator(QObject *parent = nullptr);
protected:
@@ -119,6 +125,8 @@ protected:
class Q_QUICK_PRIVATE_EXPORT QQuickXAnimator : public QQuickAnimator
{
Q_OBJECT
+ QML_NAMED_ELEMENT(XAnimator)
+ QML_ADDED_IN_MINOR_VERSION(2)
public:
QQuickXAnimator(QObject *parent = nullptr);
protected:
@@ -129,6 +137,8 @@ protected:
class Q_QUICK_PRIVATE_EXPORT QQuickYAnimator : public QQuickAnimator
{
Q_OBJECT
+ QML_NAMED_ELEMENT(YAnimator)
+ QML_ADDED_IN_MINOR_VERSION(2)
public:
QQuickYAnimator(QObject *parent = nullptr);
protected:
@@ -139,6 +149,8 @@ protected:
class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimator : public QQuickAnimator
{
Q_OBJECT
+ QML_NAMED_ELEMENT(OpacityAnimator)
+ QML_ADDED_IN_MINOR_VERSION(2)
public:
QQuickOpacityAnimator(QObject *parent = nullptr);
protected:
@@ -152,6 +164,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimator : public QQuickAnimator
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickRotationAnimator)
Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+ QML_NAMED_ELEMENT(RotationAnimator)
+ QML_ADDED_IN_MINOR_VERSION(2)
public:
enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
@@ -177,6 +191,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimator : public QQuickAnimator
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickUniformAnimator)
Q_PROPERTY(QString uniform READ uniform WRITE setUniform NOTIFY uniformChanged)
+ QML_NAMED_ELEMENT(UniformAnimator)
+ QML_ADDED_IN_MINOR_VERSION(2)
public:
QQuickUniformAnimator(QObject *parent = nullptr);
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 92d62c8d24..0112a4b337 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -207,7 +207,7 @@ void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
stop();
} else if (!m_controller && m_job) {
- m_controller = QQuickWindowPrivate::get(window)->animationController;
+ m_controller = QQuickWindowPrivate::get(window)->animationController.get();
if (window->isSceneGraphInitialized())
readyToAnimate();
else
diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h
index 66a33489e4..b0eb6fa604 100644
--- a/src/quick/util/qquickapplication_p.h
+++ b/src/quick/util/qquickapplication_p.h
@@ -71,6 +71,9 @@ class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName NOTIFY displayNameChanged)
Q_PROPERTY(QQmlListProperty<QQuickScreenInfo> screens READ screens NOTIFY screensChanged)
+ QML_NAMED_ELEMENT(Application)
+ QML_UNCREATABLE("Application is an abstract class.")
+
public:
explicit QQuickApplication(QObject *parent = nullptr);
virtual ~QQuickApplication();
diff --git a/src/quick/util/qquickbehavior_p.h b/src/quick/util/qquickbehavior_p.h
index 80a51d77af..fa9cf6d6bc 100644
--- a/src/quick/util/qquickbehavior_p.h
+++ b/src/quick/util/qquickbehavior_p.h
@@ -71,6 +71,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBehavior : public QObject, public QQmlPropert
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(QVariant targetValue READ targetValue NOTIFY targetValueChanged REVISION 13)
Q_CLASSINFO("DeferredPropertyNames", "animation")
+ QML_NAMED_ELEMENT(Behavior)
public:
QQuickBehavior(QObject *parent=nullptr);
diff --git a/src/quick/util/qquickfontloader_p.h b/src/quick/util/qquickfontloader_p.h
index 8d277f7cf7..e849c52a35 100644
--- a/src/quick/util/qquickfontloader_p.h
+++ b/src/quick/util/qquickfontloader_p.h
@@ -67,6 +67,7 @@ class Q_AUTOTEST_EXPORT QQuickFontLoader : public QObject
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ QML_NAMED_ELEMENT(FontLoader)
public:
enum Status { Null = 0, Ready, Loading, Error };
diff --git a/src/quick/util/qquickfontmetrics.cpp b/src/quick/util/qquickfontmetrics.cpp
index 42b3038c48..c9a9008180 100644
--- a/src/quick/util/qquickfontmetrics.cpp
+++ b/src/quick/util/qquickfontmetrics.cpp
@@ -327,10 +327,13 @@ QRectF QQuickFontMetrics::tightBoundingRect(const QString &text) const
/*!
\qmlmethod string QtQuick::FontMetrics::elidedText(string text, enumeration mode, real width, int flags)
- This method returns a returns an elided version of the string (i.e., a
+ This method returns an elided version of the string (i.e., a
string with "..." in it) if the string \a text is wider than \a width.
Otherwise, returns the original string.
+ The \a mode argument specifies the text elide mode; that is, where
+ the ellipsis should appear when displaying text that doesn't fit.
+
The \a flags argument is optional and currently only supports
\l {Qt::TextShowMnemonic}.
@@ -338,7 +341,7 @@ QRectF QQuickFontMetrics::tightBoundingRect(const QString &text) const
\l {QQuickTextMetrics::elidedText}{elidedText} property of
\l {QQuickTextMetrics::elidedText}{TextMetrics}.
- \sa {QFontMetricsF::elidedText()}
+ \sa Qt::TextElideMode, QFontMetricsF::elidedText()
*/
QString QQuickFontMetrics::elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags) const
{
diff --git a/src/quick/util/qquickfontmetrics_p.h b/src/quick/util/qquickfontmetrics_p.h
index db2b7b6796..ee6d679649 100644
--- a/src/quick/util/qquickfontmetrics_p.h
+++ b/src/quick/util/qquickfontmetrics_p.h
@@ -79,6 +79,8 @@ class Q_AUTOTEST_EXPORT QQuickFontMetrics : public QObject
Q_PROPERTY(qreal overlinePosition READ overlinePosition NOTIFY fontChanged)
Q_PROPERTY(qreal strikeOutPosition READ strikeOutPosition NOTIFY fontChanged)
Q_PROPERTY(qreal lineWidth READ lineWidth NOTIFY fontChanged)
+ QML_NAMED_ELEMENT(FontMetrics)
+ QML_ADDED_IN_MINOR_VERSION(4)
public:
explicit QQuickFontMetrics(QObject *parent = nullptr);
~QQuickFontMetrics();
diff --git a/src/quick/util/qquickforeignutils_p.h b/src/quick/util/qquickforeignutils_p.h
new file mode 100644
index 0000000000..7e51bc4f82
--- /dev/null
+++ b/src/quick/util/qquickforeignutils_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QTQUICKFOREIGN_P_H
+#define QTQUICKFOREIGN_P_H
+
+#include <qtquickglobal_p.h>
+
+#if QT_CONFIG(im)
+#include <QtGui/qinputmethod.h>
+#endif
+#if QT_CONFIG(validator)
+#include <QtGui/qvalidator.h>
+#endif
+#if QT_CONFIG(shortcut)
+#include <QtGui/qkeysequence.h>
+#endif
+
+#include <QtQml/qqml.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(validator)
+struct QValidatorForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QValidator)
+ QML_ANONYMOUS
+};
+
+struct QRegExpValidatorForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QRegExpValidator)
+ QML_NAMED_ELEMENT(RegExpValidator)
+};
+
+#if QT_CONFIG(regularexpression)
+struct QRegularExpressionValidatorForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QRegularExpressionValidator)
+ QML_NAMED_ELEMENT(RegularExpressionValidator)
+ QML_ADDED_IN_MINOR_VERSION(14)
+};
+#endif // QT_CONFIG(regularexpression)
+
+#endif // QT_CONFIG(validator)
+
+#if QT_CONFIG(im)
+struct QInputMethodForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QInputMethod)
+ QML_NAMED_ELEMENT(InputMethod)
+ QML_UNCREATABLE("InputMethod is an abstract class.")
+};
+#endif // QT_CONFIG(im)
+
+#if QT_CONFIG(shortcut)
+struct QKeySequenceForeign
+{
+ Q_GADGET
+ QML_FOREIGN(QKeySequence)
+ QML_NAMED_ELEMENT(StandardKey)
+ QML_ADDED_IN_MINOR_VERSION(2)
+ QML_UNCREATABLE("Cannot create an instance of StandardKey.")
+};
+#endif // QT_CONFIG(shortcut)
+
+QT_END_NAMESPACE
+
+#endif // QTQUICKFOREIGN_P_H
diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h
index 5987ae8f35..ca0495a90d 100644
--- a/src/quick/util/qquickpath_p.h
+++ b/src/quick/util/qquickpath_p.h
@@ -77,6 +77,7 @@ struct QQuickPathData
class Q_QUICK_PRIVATE_EXPORT QQuickPathElement : public QObject
{
Q_OBJECT
+ QML_ANONYMOUS
public:
QQuickPathElement(QObject *parent=nullptr) : QObject(parent) {}
Q_SIGNALS:
@@ -89,6 +90,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathAttribute : public QQuickPathElement
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+ QML_NAMED_ELEMENT(PathAttribute)
public:
QQuickPathAttribute(QObject *parent=nullptr) : QQuickPathElement(parent) {}
@@ -116,6 +118,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickCurve : public QQuickPathElement
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
Q_PROPERTY(qreal relativeX READ relativeX WRITE setRelativeX NOTIFY relativeXChanged)
Q_PROPERTY(qreal relativeY READ relativeY WRITE setRelativeY NOTIFY relativeYChanged)
+ QML_ANONYMOUS
public:
QQuickCurve(QObject *parent=nullptr) : QQuickPathElement(parent) {}
@@ -153,6 +156,7 @@ private:
class Q_QUICK_PRIVATE_EXPORT QQuickPathLine : public QQuickCurve
{
Q_OBJECT
+ QML_NAMED_ELEMENT(PathLine)
public:
QQuickPathLine(QObject *parent=nullptr) : QQuickCurve(parent) {}
@@ -162,6 +166,8 @@ public:
class Q_QUICK_PRIVATE_EXPORT QQuickPathMove : public QQuickCurve
{
Q_OBJECT
+ QML_NAMED_ELEMENT(PathMove)
+ QML_ADDED_IN_MINOR_VERSION(9)
public:
QQuickPathMove(QObject *parent=nullptr) : QQuickCurve(parent) {}
@@ -176,6 +182,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathQuad : public QQuickCurve
Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY controlYChanged)
Q_PROPERTY(qreal relativeControlX READ relativeControlX WRITE setRelativeControlX NOTIFY relativeControlXChanged)
Q_PROPERTY(qreal relativeControlY READ relativeControlY WRITE setRelativeControlY NOTIFY relativeControlYChanged)
+
+ QML_NAMED_ELEMENT(PathQuad)
public:
QQuickPathQuad(QObject *parent=nullptr) : QQuickCurve(parent) {}
@@ -220,6 +228,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathCubic : public QQuickCurve
Q_PROPERTY(qreal relativeControl1Y READ relativeControl1Y WRITE setRelativeControl1Y NOTIFY relativeControl1YChanged)
Q_PROPERTY(qreal relativeControl2X READ relativeControl2X WRITE setRelativeControl2X NOTIFY relativeControl2XChanged)
Q_PROPERTY(qreal relativeControl2Y READ relativeControl2Y WRITE setRelativeControl2Y NOTIFY relativeControl2YChanged)
+ QML_NAMED_ELEMENT(PathCubic)
public:
QQuickPathCubic(QObject *parent=nullptr) : QQuickCurve(parent) {}
@@ -277,6 +286,7 @@ private:
class Q_QUICK_PRIVATE_EXPORT QQuickPathCatmullRomCurve : public QQuickCurve
{
Q_OBJECT
+ QML_NAMED_ELEMENT(PathCurve)
public:
QQuickPathCatmullRomCurve(QObject *parent=nullptr) : QQuickCurve(parent) {}
@@ -291,6 +301,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathArc : public QQuickCurve
Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION 9)
+ QML_NAMED_ELEMENT(PathArc)
public:
QQuickPathArc(QObject *parent=nullptr)
@@ -342,6 +353,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathAngleArc : public QQuickCurve
Q_PROPERTY(qreal sweepAngle READ sweepAngle WRITE setSweepAngle NOTIFY sweepAngleChanged)
Q_PROPERTY(bool moveToStart READ moveToStart WRITE setMoveToStart NOTIFY moveToStartChanged)
+ QML_NAMED_ELEMENT(PathAngleArc)
+ QML_ADDED_IN_MINOR_VERSION(11)
+
public:
QQuickPathAngleArc(QObject *parent=nullptr)
: QQuickCurve(parent) {}
@@ -392,6 +406,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathSvg : public QQuickCurve
{
Q_OBJECT
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
+ QML_NAMED_ELEMENT(PathSvg)
public:
QQuickPathSvg(QObject *parent=nullptr) : QQuickCurve(parent) {}
@@ -411,6 +426,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathPercent : public QQuickPathElement
{
Q_OBJECT
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+ QML_NAMED_ELEMENT(PathPercent)
public:
QQuickPathPercent(QObject *parent=nullptr) : QQuickPathElement(parent) {}
@@ -429,6 +445,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathPolyline : public QQuickCurve
Q_OBJECT
Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
Q_PROPERTY(QVariant path READ path WRITE setPath NOTIFY pathChanged)
+ QML_NAMED_ELEMENT(PathPolyline)
+ QML_ADDED_IN_MINOR_VERSION(14)
public:
QQuickPathPolyline(QObject *parent=nullptr);
@@ -451,6 +469,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathMultiline : public QQuickCurve
Q_OBJECT
Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
Q_PROPERTY(QVariant paths READ paths WRITE setPaths NOTIFY pathsChanged)
+ QML_NAMED_ELEMENT(PathMultiline)
+ QML_ADDED_IN_MINOR_VERSION(14)
public:
QQuickPathMultiline(QObject *parent=nullptr);
@@ -493,6 +513,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPath : public QObject, public QQmlParserStatu
Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14)
Q_CLASSINFO("DefaultProperty", "pathElements")
+ QML_NAMED_ELEMENT(Path)
Q_INTERFACES(QQmlParserStatus)
public:
QQuickPath(QObject *parent=nullptr);
diff --git a/src/quick/util/qquickpathinterpolator_p.h b/src/quick/util/qquickpathinterpolator_p.h
index 60a9ff2e22..440ea06841 100644
--- a/src/quick/util/qquickpathinterpolator_p.h
+++ b/src/quick/util/qquickpathinterpolator_p.h
@@ -69,6 +69,7 @@ class Q_AUTOTEST_EXPORT QQuickPathInterpolator : public QObject
Q_PROPERTY(qreal x READ x NOTIFY xChanged)
Q_PROPERTY(qreal y READ y NOTIFY yChanged)
Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged)
+ QML_NAMED_ELEMENT(PathInterpolator)
public:
explicit QQuickPathInterpolator(QObject *parent = nullptr);
diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h
index 82a6ebffac..27a00420af 100644
--- a/src/quick/util/qquickpropertychanges_p.h
+++ b/src/quick/util/qquickpropertychanges_p.h
@@ -65,6 +65,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPropertyChanges : public QQuickStateOperation
Q_PROPERTY(QObject *target READ object WRITE setObject)
Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
+ QML_NAMED_ELEMENT(PropertyChanges)
+
public:
QQuickPropertyChanges();
~QQuickPropertyChanges();
@@ -107,6 +109,11 @@ public:
void applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
+template<>
+inline QQmlCustomParser *qmlCreateCustomParser<QQuickPropertyChanges>()
+{
+ return new QQuickPropertyChangesParser;
+}
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 730a14369e..5d227b4613 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -216,7 +216,7 @@ void QQuickShortcut::setSequences(const QVariantList &values)
bool changed = !remainder.isEmpty();
for (int i = 0; i < values.count(); ++i) {
- QVariant value = values.at(i);
+ const QVariant &value = values.at(i);
Shortcut& shortcut = m_shortcuts[i];
if (value == shortcut.userValue)
continue;
diff --git a/src/quick/util/qquickshortcut_p.h b/src/quick/util/qquickshortcut_p.h
index 712cca7696..0e66a38e75 100644
--- a/src/quick/util/qquickshortcut_p.h
+++ b/src/quick/util/qquickshortcut_p.h
@@ -56,6 +56,7 @@
#include <QtCore/qvariant.h>
#include <QtGui/qkeysequence.h>
#include <QtQml/qqmlparserstatus.h>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -72,6 +73,8 @@ class QQuickShortcut : public QObject, public QQmlParserStatus
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL)
Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL)
Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext NOTIFY contextChanged FINAL)
+ QML_NAMED_ELEMENT(Shortcut)
+ QML_ADDED_IN_MINOR_VERSION(5)
public:
explicit QQuickShortcut(QObject *parent = nullptr);
diff --git a/src/quick/util/qquicksmoothedanimation_p.h b/src/quick/util/qquicksmoothedanimation_p.h
index 7bceba387c..d7e637446d 100644
--- a/src/quick/util/qquicksmoothedanimation_p.h
+++ b/src/quick/util/qquicksmoothedanimation_p.h
@@ -68,6 +68,7 @@ class Q_AUTOTEST_EXPORT QQuickSmoothedAnimation : public QQuickNumberAnimation
Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged)
+ QML_NAMED_ELEMENT(SmoothedAnimation)
public:
enum ReversingMode { Eased, Immediate, Sync };
diff --git a/src/quick/util/qquickspringanimation_p.h b/src/quick/util/qquickspringanimation_p.h
index 2014a4311a..771b746622 100644
--- a/src/quick/util/qquickspringanimation_p.h
+++ b/src/quick/util/qquickspringanimation_p.h
@@ -71,6 +71,7 @@ class Q_AUTOTEST_EXPORT QQuickSpringAnimation : public QQuickNumberAnimation
Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon)
Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged)
Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged)
+ QML_NAMED_ELEMENT(SpringAnimation)
public:
QQuickSpringAnimation(QObject *parent=nullptr);
diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h
index 576ba9834c..af49bb1c2f 100644
--- a/src/quick/util/qquickstate_p.h
+++ b/src/quick/util/qquickstate_p.h
@@ -125,6 +125,7 @@ class QQuickStateOperationPrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickStateOperation : public QObject
{
Q_OBJECT
+ QML_ANONYMOUS
public:
QQuickStateOperation(QObject *parent = nullptr)
: QObject(parent) {}
@@ -157,6 +158,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickState : public QObject
Q_PROPERTY(QQmlListProperty<QQuickStateOperation> changes READ changes)
Q_CLASSINFO("DefaultProperty", "changes")
Q_CLASSINFO("DeferredPropertyNames", "changes")
+ QML_NAMED_ELEMENT(State)
public:
QQuickState(QObject *parent=nullptr);
diff --git a/src/quick/util/qquickstatechangescript_p.h b/src/quick/util/qquickstatechangescript_p.h
index ff509a7cf5..931baaca4e 100644
--- a/src/quick/util/qquickstatechangescript_p.h
+++ b/src/quick/util/qquickstatechangescript_p.h
@@ -64,6 +64,7 @@ class Q_AUTOTEST_EXPORT QQuickStateChangeScript : public QQuickStateOperation, p
Q_PROPERTY(QQmlScriptString script READ script WRITE setScript)
Q_PROPERTY(QString name READ name WRITE setName)
+ QML_NAMED_ELEMENT(StateChangeScript)
public:
QQuickStateChangeScript(QObject *parent=nullptr);
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
index 0adae82dcc..46e7d62fc1 100644
--- a/src/quick/util/qquickstategroup.cpp
+++ b/src/quick/util/qquickstategroup.cpp
@@ -311,7 +311,7 @@ void QQuickStateGroup::componentComplete()
if (!state->isNamed())
state->setName(QLatin1String("anonymousState") + QString::number(++d->unnamedCount));
- const QString stateName = state->name();
+ QString stateName = state->name();
if (names.contains(stateName)) {
qmlWarning(state->parent()) << "Found duplicate state name: " << stateName;
} else {
diff --git a/src/quick/util/qquickstategroup_p.h b/src/quick/util/qquickstategroup_p.h
index 7235066d99..11a0c5f442 100644
--- a/src/quick/util/qquickstategroup_p.h
+++ b/src/quick/util/qquickstategroup_p.h
@@ -65,6 +65,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickStateGroup : public QObject, public QQmlParse
Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
Q_PROPERTY(QQmlListProperty<QQuickState> states READ statesProperty DESIGNABLE false)
Q_PROPERTY(QQmlListProperty<QQuickTransition> transitions READ transitionsProperty DESIGNABLE false)
+ QML_NAMED_ELEMENT(StateGroup)
public:
QQuickStateGroup(QObject * = nullptr);
diff --git a/src/quick/util/qquicksystempalette_p.h b/src/quick/util/qquicksystempalette_p.h
index 9a3a520ed1..c6d9fc2604 100644
--- a/src/quick/util/qquicksystempalette_p.h
+++ b/src/quick/util/qquicksystempalette_p.h
@@ -79,6 +79,7 @@ class Q_AUTOTEST_EXPORT QQuickSystemPalette : public QObject
Q_PROPERTY(QColor shadow READ shadow NOTIFY paletteChanged)
Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged)
Q_PROPERTY(QColor highlightedText READ highlightedText NOTIFY paletteChanged)
+ QML_NAMED_ELEMENT(SystemPalette)
public:
QQuickSystemPalette(QObject *parent=nullptr);
diff --git a/src/quick/util/qquicktextmetrics_p.h b/src/quick/util/qquicktextmetrics_p.h
index 4fb6741996..a1d64e3d0a 100644
--- a/src/quick/util/qquicktextmetrics_p.h
+++ b/src/quick/util/qquicktextmetrics_p.h
@@ -74,6 +74,8 @@ class Q_AUTOTEST_EXPORT QQuickTextMetrics : public QObject
Q_PROPERTY(QString elidedText READ elidedText NOTIFY metricsChanged FINAL)
Q_PROPERTY(Qt::TextElideMode elide READ elide WRITE setElide NOTIFY elideChanged FINAL)
Q_PROPERTY(qreal elideWidth READ elideWidth WRITE setElideWidth NOTIFY elideWidthChanged FINAL)
+ QML_NAMED_ELEMENT(TextMetrics)
+ QML_ADDED_IN_MINOR_VERSION(4)
public:
explicit QQuickTextMetrics(QObject *parent = 0);
diff --git a/src/quick/util/qquicktransition_p.h b/src/quick/util/qquicktransition_p.h
index c7d06b8832..6e45143126 100644
--- a/src/quick/util/qquicktransition_p.h
+++ b/src/quick/util/qquicktransition_p.h
@@ -103,6 +103,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTransition : public QObject
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_CLASSINFO("DefaultProperty", "animations")
Q_CLASSINFO("DeferredPropertyNames", "animations")
+ QML_NAMED_ELEMENT(Transition)
public:
QQuickTransition(QObject *parent=nullptr);
diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp
index 93b6599506..650a8c7e81 100644
--- a/src/quick/util/qquickutilmodule.cpp
+++ b/src/quick/util/qquickutilmodule.cpp
@@ -40,6 +40,7 @@
#include "qquickutilmodule_p.h"
#include "qquickanimation_p.h"
#include "qquickanimation_p_p.h"
+#include "qquickapplication_p.h"
#include "qquickbehavior_p.h"
#include "qquicksmoothedanimation_p.h"
#include "qquickfontloader_p.h"
@@ -58,12 +59,11 @@
#include "qquickshortcut_p.h"
#endif
#include "qquickvalidator_p.h"
+#include "qquickforeignutils_p.h"
#include <qqmlinfo.h>
#include <private/qqmltypenotavailable_p.h>
#include <private/qquickanimationcontroller_p.h>
#include <QtCore/qcoreapplication.h>
-#include <QtGui/QInputMethod>
-#include <QtGui/QKeySequence>
#if QT_CONFIG(shortcut)
Q_DECLARE_METATYPE(QKeySequence::StandardKey)
@@ -71,73 +71,61 @@ Q_DECLARE_METATYPE(QKeySequence::StandardKey)
void QQuickUtilModule::defineModule()
{
-#if QT_CONFIG(im)
- qmlRegisterUncreatableType<QInputMethod>("QtQuick",2,0,"InputMethod",
- QInputMethod::tr("InputMethod is an abstract class"));
+#if QT_CONFIG(shortcut)
+ qRegisterMetaType<QKeySequence::StandardKey>();
#endif
- qmlRegisterUncreatableType<QQuickAbstractAnimation>("QtQuick",2,0,"Animation",QQuickAbstractAnimation::tr("Animation is an abstract class"));
-
- qmlRegisterType<QQuickBehavior>("QtQuick",2,0,"Behavior");
- qmlRegisterType<QQuickColorAnimation>("QtQuick",2,0,"ColorAnimation");
- qmlRegisterType<QQuickSmoothedAnimation>("QtQuick",2,0,"SmoothedAnimation");
- qmlRegisterType<QQuickFontLoader>("QtQuick",2,0,"FontLoader");
- qmlRegisterType<QQuickNumberAnimation>("QtQuick",2,0,"NumberAnimation");
- qmlRegisterType<QQuickParallelAnimation>("QtQuick",2,0,"ParallelAnimation");
- qmlRegisterType<QQuickPauseAnimation>("QtQuick",2,0,"PauseAnimation");
- qmlRegisterType<QQuickPropertyAction>("QtQuick",2,0,"PropertyAction");
- qmlRegisterType<QQuickPropertyAnimation>("QtQuick",2,0,"PropertyAnimation");
- qmlRegisterType<QQuickRotationAnimation>("QtQuick",2,0,"RotationAnimation");
- qmlRegisterType<QQuickScriptAction>("QtQuick",2,0,"ScriptAction");
- qmlRegisterType<QQuickSequentialAnimation>("QtQuick",2,0,"SequentialAnimation");
- qmlRegisterType<QQuickSpringAnimation>("QtQuick",2,0,"SpringAnimation");
- qmlRegisterType<QQuickAnimationController>("QtQuick",2,0,"AnimationController");
- qmlRegisterType<QQuickStateChangeScript>("QtQuick",2,0,"StateChangeScript");
- qmlRegisterType<QQuickStateGroup>("QtQuick",2,0,"StateGroup");
- qmlRegisterType<QQuickState>("QtQuick",2,0,"State");
- qmlRegisterType<QQuickSystemPalette>("QtQuick",2,0,"SystemPalette");
- qmlRegisterType<QQuickTransition>("QtQuick",2,0,"Transition");
- qmlRegisterType<QQuickVector3dAnimation>("QtQuick",2,0,"Vector3dAnimation");
+ qmlRegisterTypesAndRevisions<
#if QT_CONFIG(validator)
- qmlRegisterAnonymousType<QValidator>("QtQuick", 2);
- qmlRegisterType<QQuickIntValidator>("QtQuick",2,0,"IntValidator");
- qmlRegisterType<QQuickDoubleValidator>("QtQuick",2,0,"DoubleValidator");
- qmlRegisterType<QRegExpValidator>("QtQuick",2,0,"RegExpValidator");
+ QValidatorForeign,
+ QQuickIntValidator,
+ QQuickDoubleValidator,
+ QRegExpValidatorForeign,
#if QT_CONFIG(regularexpression)
- qmlRegisterType<QRegularExpressionValidator>("QtQuick", 2, 14, "RegularExpressionValidator");
-#endif
-#endif
-
- qmlRegisterUncreatableType<QQuickAnimator>("QtQuick", 2, 2, "Animator", QQuickAbstractAnimation::tr("Animator is an abstract class"));
- qmlRegisterType<QQuickXAnimator>("QtQuick", 2, 2, "XAnimator");
- qmlRegisterType<QQuickYAnimator>("QtQuick", 2, 2, "YAnimator");
- qmlRegisterType<QQuickScaleAnimator>("QtQuick", 2, 2, "ScaleAnimator");
- qmlRegisterType<QQuickRotationAnimator>("QtQuick", 2, 2, "RotationAnimator");
- qmlRegisterType<QQuickOpacityAnimator>("QtQuick", 2, 2, "OpacityAnimator");
+ QRegularExpressionValidatorForeign,
+#endif // QT_CONFIG(regularexpression)
+#endif // QT_CONFIG(validator)
#if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl)
- qmlRegisterType<QQuickUniformAnimator>("QtQuick", 2, 2, "UniformAnimator");
+ QQuickUniformAnimator,
#endif
- qmlRegisterAnonymousType<QQuickStateOperation>("QtQuick", 2);
-
- qmlRegisterCustomType<QQuickPropertyChanges>("QtQuick",2,0,"PropertyChanges", new QQuickPropertyChangesParser);
-
#if QT_CONFIG(shortcut)
- qRegisterMetaType<QKeySequence::StandardKey>();
- qmlRegisterUncreatableType<QKeySequence, 2>("QtQuick", 2, 2, "StandardKey", QStringLiteral("Cannot create an instance of StandardKey."));
+ QQuickShortcut,
+ QKeySequenceForeign,
#endif
-
- qmlRegisterType<QQuickFontMetrics>("QtQuick", 2, 4, "FontMetrics");
- qmlRegisterType<QQuickTextMetrics>("QtQuick", 2, 4, "TextMetrics");
-
-#if QT_CONFIG(shortcut)
- qmlRegisterType<QQuickShortcut>("QtQuick", 2, 5, "Shortcut");
- qmlRegisterType<QQuickShortcut,6>("QtQuick", 2, 6, "Shortcut");
-
- qmlRegisterType<QQuickShortcut,9>("QtQuick", 2, 9, "Shortcut");
+#if QT_CONFIG(im)
+ QInputMethodForeign,
#endif
-
- qmlRegisterUncreatableType<QQuickAbstractAnimation, 12>("QtQuick", 2, 12, "Animation",
- QQuickAbstractAnimation::tr("Animation is an abstract class"));
- // 5.13
- qmlRegisterType<QQuickBehavior, 13>("QtQuick", 2, 13, "Behavior");
+ QQuickAbstractAnimation,
+ QQuickBehavior,
+ QQuickColorAnimation,
+ QQuickSmoothedAnimation,
+ QQuickFontLoader,
+ QQuickNumberAnimation,
+ QQuickParallelAnimation,
+ QQuickPauseAnimation,
+ QQuickPropertyAction,
+ QQuickPropertyAnimation,
+ QQuickRotationAnimation,
+ QQuickScriptAction,
+ QQuickSequentialAnimation,
+ QQuickSpringAnimation,
+ QQuickAnimationController,
+ QQuickStateChangeScript,
+ QQuickStateGroup,
+ QQuickState,
+ QQuickSystemPalette,
+ QQuickTransition,
+ QQuickVector3dAnimation,
+ QQuickAnimator,
+ QQuickXAnimator,
+ QQuickYAnimator,
+ QQuickScaleAnimator,
+ QQuickRotationAnimator,
+ QQuickOpacityAnimator,
+ QQuickStateOperation,
+ QQuickPropertyChanges,
+ QQuickFontMetrics,
+ QQuickTextMetrics,
+ QQuickApplication
+ >("QtQuick", 2);
}
diff --git a/src/quick/util/qquickvalidator_p.h b/src/quick/util/qquickvalidator_p.h
index 9212efa044..a0dc2cd5ba 100644
--- a/src/quick/util/qquickvalidator_p.h
+++ b/src/quick/util/qquickvalidator_p.h
@@ -61,6 +61,7 @@ class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator
{
Q_OBJECT
Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
+ QML_NAMED_ELEMENT(IntValidator)
public:
QQuickIntValidator(QObject *parent = nullptr);
@@ -76,6 +77,7 @@ class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator
{
Q_OBJECT
Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
+ QML_NAMED_ELEMENT(DoubleValidator)
public:
QQuickDoubleValidator(QObject *parent = nullptr);
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index e4a03f3b52..0af29aed1c 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -109,6 +109,11 @@ qreal QQuickColorValueType::hslLightness() const
return v.lightnessF();
}
+bool QQuickColorValueType::isValid() const
+{
+ return v.isValid();
+}
+
void QQuickColorValueType::setR(qreal r)
{
v.setRedF(r);
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index 5a9af970e8..91e3815d5b 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -84,6 +84,7 @@ class QQuickColorValueType
Q_PROPERTY(qreal hslHue READ hslHue WRITE setHslHue FINAL)
Q_PROPERTY(qreal hslSaturation READ hslSaturation WRITE setHslSaturation FINAL)
Q_PROPERTY(qreal hslLightness READ hslLightness WRITE setHslLightness FINAL)
+ Q_PROPERTY(bool valid READ isValid)
Q_GADGET
public:
Q_INVOKABLE QString toString() const;
@@ -98,6 +99,7 @@ public:
qreal hslHue() const;
qreal hslSaturation() const;
qreal hslLightness() const;
+ bool isValid() const;
void setR(qreal);
void setG(qreal);
void setB(qreal);
@@ -326,6 +328,9 @@ class QQuickFontValueType
Q_PROPERTY(bool kerning READ kerning WRITE setKerning FINAL)
Q_PROPERTY(bool preferShaping READ preferShaping WRITE setPreferShaping FINAL)
+ QML_NAMED_ELEMENT(Font)
+ QML_UNCREATABLE("Element is not creatable.")
+
public:
enum FontWeight { Thin = QFont::Thin,
ExtraLight = QFont::ExtraLight,
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index 63d995e34c..3a1addfcd4 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -15,7 +15,6 @@ SOURCES += \
$$PWD/qquicktimeline.cpp \
$$PWD/qquickpixmapcache.cpp \
$$PWD/qquickbehavior.cpp \
- $$PWD/qquickboundaryrule.cpp \
$$PWD/qquickfontloader.cpp \
$$PWD/qquickstyledtext.cpp \
$$PWD/qquickimageprovider.cpp \
@@ -51,7 +50,6 @@ HEADERS += \
$$PWD/qquicktimeline_p_p.h \
$$PWD/qquickpixmapcache_p.h \
$$PWD/qquickbehavior_p.h \
- $$PWD/qquickboundaryrule_p.h \
$$PWD/qquickfontloader_p.h \
$$PWD/qquickstyledtext_p.h \
$$PWD/qquickimageprovider.h \
@@ -65,7 +63,8 @@ HEADERS += \
$$PWD/qquickprofiler_p.h \
$$PWD/qquickfontmetrics_p.h \
$$PWD/qquicktextmetrics_p.h \
- $$PWD/qquickvalidator_p.h
+ $$PWD/qquickvalidator_p.h \
+ $$PWD/qquickforeignutils_p.h
qtConfig(shortcut) {
SOURCES += \
diff --git a/src/quickshapes/qquickshape.cpp b/src/quickshapes/qquickshape.cpp
index c1deb0dced..a7db65f16f 100644
--- a/src/quickshapes/qquickshape.cpp
+++ b/src/quickshapes/qquickshape.cpp
@@ -90,7 +90,7 @@ QQuickShapeStrokeFillParams::QQuickShapeStrokeFillParams()
/*!
\qmltype ShapePath
- \instantiates QQuickShapePath
+ //! \instantiates QQuickShapePath
\inqmlmodule QtQuick.Shapes
\ingroup qtquick-paths
\ingroup qtquick-views
@@ -517,7 +517,7 @@ void QQuickShapePath::resetFillGradient()
/*!
\qmltype Shape
- \instantiates QQuickShape
+ //! \instantiates QQuickShape
\inqmlmodule QtQuick.Shapes
\ingroup qtquick-paths
\ingroup qtquick-views
@@ -1142,7 +1142,7 @@ void QQuickShapePrivate::sync()
/*!
\qmltype ShapeGradient
- \instantiates QQuickShapeGradient
+ //! \instantiates QQuickShapeGradient
\inqmlmodule QtQuick.Shapes
\ingroup qtquick-paths
\ingroup qtquick-views
@@ -1193,7 +1193,7 @@ void QQuickShapeGradient::setSpread(SpreadMode mode)
/*!
\qmltype LinearGradient
- \instantiates QQuickShapeLinearGradient
+ //! \instantiates QQuickShapeLinearGradient
\inqmlmodule QtQuick.Shapes
\ingroup qtquick-paths
\ingroup qtquick-views
@@ -1284,7 +1284,7 @@ void QQuickShapeLinearGradient::setY2(qreal v)
/*!
\qmltype RadialGradient
- \instantiates QQuickShapeRadialGradient
+ //! \instantiates QQuickShapeRadialGradient
\inqmlmodule QtQuick.Shapes
\ingroup qtquick-paths
\ingroup qtquick-views
@@ -1437,7 +1437,7 @@ void QQuickShapeRadialGradient::setFocalRadius(qreal v)
/*!
\qmltype ConicalGradient
- \instantiates QQuickShapeConicalGradient
+ //! \instantiates QQuickShapeConicalGradient
\inqmlmodule QtQuick.Shapes
\ingroup qtquick-paths
\ingroup qtquick-views
diff --git a/src/quickshapes/qquickshape_p.h b/src/quickshapes/qquickshape_p.h
index 7066ea0709..cadc65f7cd 100644
--- a/src/quickshapes/qquickshape_p.h
+++ b/src/quickshapes/qquickshape_p.h
@@ -69,6 +69,9 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeGradient : public QQuickGradient
Q_PROPERTY(SpreadMode spread READ spread WRITE setSpread NOTIFY spreadChanged)
Q_CLASSINFO("DefaultProperty", "stops")
+ QML_NAMED_ELEMENT(ShapeGradient)
+ QML_UNCREATABLE("ShapeGradient is an abstract base class.");
+
public:
enum SpreadMode {
PadSpread,
@@ -97,6 +100,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeLinearGradient : public QQuickShap
Q_PROPERTY(qreal x2 READ x2 WRITE setX2 NOTIFY x2Changed)
Q_PROPERTY(qreal y2 READ y2 WRITE setY2 NOTIFY y2Changed)
Q_CLASSINFO("DefaultProperty", "stops")
+ QML_NAMED_ELEMENT(LinearGradient)
public:
QQuickShapeLinearGradient(QObject *parent = nullptr);
@@ -131,6 +135,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeRadialGradient : public QQuickShap
Q_PROPERTY(qreal focalY READ focalY WRITE setFocalY NOTIFY focalYChanged)
Q_PROPERTY(qreal focalRadius READ focalRadius WRITE setFocalRadius NOTIFY focalRadiusChanged)
Q_CLASSINFO("DefaultProperty", "stops")
+ QML_NAMED_ELEMENT(RadialGradient)
public:
QQuickShapeRadialGradient(QObject *parent = nullptr);
@@ -175,6 +180,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeConicalGradient : public QQuickSha
Q_PROPERTY(qreal centerY READ centerY WRITE setCenterY NOTIFY centerYChanged)
Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
Q_CLASSINFO("DefaultProperty", "stops")
+ QML_NAMED_ELEMENT(ConicalGradient)
public:
QQuickShapeConicalGradient(QObject *parent = nullptr);
@@ -214,6 +220,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapePath : public QQuickPath
Q_PROPERTY(QVector<qreal> dashPattern READ dashPattern WRITE setDashPattern NOTIFY dashPatternChanged)
Q_PROPERTY(QQuickShapeGradient *fillGradient READ fillGradient WRITE setFillGradient RESET resetFillGradient)
Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14)
+ QML_NAMED_ELEMENT(ShapePath)
public:
enum FillRule {
@@ -308,6 +315,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShape : public QQuickItem
Q_PROPERTY(ContainsMode containsMode READ containsMode WRITE setContainsMode NOTIFY containsModeChanged REVISION 11)
Q_PROPERTY(QQmlListProperty<QObject> data READ data)
Q_CLASSINFO("DefaultProperty", "data")
+ QML_NAMED_ELEMENT(Shape)
public:
enum RendererType {
diff --git a/src/quickshapes/qquickshapegenericrenderer.cpp b/src/quickshapes/qquickshapegenericrenderer.cpp
index 6ddd055d85..06cc442fc7 100644
--- a/src/quickshapes/qquickshapegenericrenderer.cpp
+++ b/src/quickshapes/qquickshapegenericrenderer.cpp
@@ -795,7 +795,7 @@ QQuickShapeLinearGradientRhiShader::QQuickShapeLinearGradientRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/lineargradient.frag.qsb"));
}
-bool QQuickShapeLinearGradientRhiShader::updateUniformData(const RenderState &state,
+bool QQuickShapeLinearGradientRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
@@ -834,7 +834,7 @@ bool QQuickShapeLinearGradientRhiShader::updateUniformData(const RenderState &st
return changed;
}
-void QQuickShapeLinearGradientRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void QQuickShapeLinearGradientRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *)
{
if (binding != 1)
@@ -968,7 +968,7 @@ QQuickShapeRadialGradientRhiShader::QQuickShapeRadialGradientRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/radialgradient.frag.qsb"));
}
-bool QQuickShapeRadialGradientRhiShader::updateUniformData(const RenderState &state,
+bool QQuickShapeRadialGradientRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
@@ -1026,7 +1026,7 @@ bool QQuickShapeRadialGradientRhiShader::updateUniformData(const RenderState &st
return changed;
}
-void QQuickShapeRadialGradientRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void QQuickShapeRadialGradientRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *)
{
if (binding != 1)
@@ -1158,7 +1158,7 @@ QQuickShapeConicalGradientRhiShader::QQuickShapeConicalGradientRhiShader()
setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/conicalgradient.frag.qsb"));
}
-bool QQuickShapeConicalGradientRhiShader::updateUniformData(const RenderState &state,
+bool QQuickShapeConicalGradientRhiShader::updateUniformData(RenderState &state,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
@@ -1200,7 +1200,7 @@ bool QQuickShapeConicalGradientRhiShader::updateUniformData(const RenderState &s
return changed;
}
-void QQuickShapeConicalGradientRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+void QQuickShapeConicalGradientRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *)
{
if (binding != 1)
diff --git a/src/quickshapes/qquickshapegenericrenderer_p.h b/src/quickshapes/qquickshapegenericrenderer_p.h
index 3398159bf6..4590c662c1 100644
--- a/src/quickshapes/qquickshapegenericrenderer_p.h
+++ b/src/quickshapes/qquickshapegenericrenderer_p.h
@@ -267,9 +267,9 @@ class QQuickShapeLinearGradientRhiShader : public QSGMaterialRhiShader
public:
QQuickShapeLinearGradientRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial,
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
private:
@@ -328,9 +328,9 @@ class QQuickShapeRadialGradientRhiShader : public QSGMaterialRhiShader
public:
QQuickShapeRadialGradientRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial,
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
private:
@@ -384,9 +384,9 @@ class QQuickShapeConicalGradientRhiShader : public QSGMaterialRhiShader
public:
QQuickShapeConicalGradientRhiShader();
- bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial,
+ bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
QSGMaterial *oldMaterial) override;
- void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture,
+ void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
private:
diff --git a/src/quickshapes/qquickshapenvprrenderer.cpp b/src/quickshapes/qquickshapenvprrenderer.cpp
index a5b2a3467c..721091b669 100644
--- a/src/quickshapes/qquickshapenvprrenderer.cpp
+++ b/src/quickshapes/qquickshapenvprrenderer.cpp
@@ -177,7 +177,7 @@ QDebug operator<<(QDebug debug, const QQuickShapeNvprRenderer::NvprPath &path)
debug << "Path with" << path.cmd.count() << "commands";
int ci = 0;
for (GLubyte cmd : path.cmd) {
- static struct { GLubyte cmd; const char *s; int coordCount; } nameTab[] = {
+ static struct { GLubyte cmd; const char *s; int coordCount; } nameTabs[] = {
{ GL_MOVE_TO_NV, "moveTo", 2 },
{ GL_LINE_TO_NV, "lineTo", 2 },
{ GL_QUADRATIC_CURVE_TO_NV, "quadTo", 4 },
@@ -187,14 +187,14 @@ QDebug operator<<(QDebug debug, const QQuickShapeNvprRenderer::NvprPath &path)
{ GL_SMALL_CW_ARC_TO_NV, "arcTo-small-CW", 5 },
{ GL_SMALL_CCW_ARC_TO_NV, "arcTo-small-CCW", 5 },
{ GL_CLOSE_PATH_NV, "closePath", 0 } };
- for (size_t i = 0; i < sizeof(nameTab) / sizeof(nameTab[0]); ++i) {
- if (nameTab[i].cmd == cmd) {
+ for (const auto &nameTab : nameTabs) {
+ if (nameTab.cmd == cmd) {
QByteArray cs;
- for (int j = 0; j < nameTab[i].coordCount; ++j) {
+ for (int j = 0; j < nameTab.coordCount; ++j) {
cs.append(QByteArray::number(path.coord[ci++]));
cs.append(' ');
}
- debug << "\n " << nameTab[i].s << " " << cs;
+ debug << "\n " << nameTab.s << " " << cs;
break;
}
}
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index b16bfee6a6..4d2914ff6c 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -283,7 +283,16 @@ void QQuickWidgetPrivate::render(bool needsSync)
Q_ASSERT(context);
- if (!context->makeCurrent(offscreenSurface)) {
+ bool current = context->makeCurrent(offscreenSurface);
+
+ if (!current && !context->isValid()) {
+ renderControl->invalidate();
+ current = context->create() && context->makeCurrent(offscreenSurface);
+ if (current)
+ renderControl->initialize(context);
+ }
+
+ if (!current) {
qWarning("QQuickWidget: Cannot render due to failing makeCurrent()");
return;
}
@@ -1119,6 +1128,13 @@ GLuint QQuickWidgetPrivate::textureId() const
return resolvedFbo ? resolvedFbo->texture()
: (fbo ? fbo->texture() : 0);
}
+
+QPlatformTextureList::Flags QQuickWidgetPrivate::textureListFlags()
+{
+ QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags();
+ flags |= QPlatformTextureList::NeedsPremultipliedAlphaBlending;
+ return flags;
+}
#endif
/*!
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index 03571e8dc7..f4f9db7772 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -101,6 +101,7 @@ public:
#if QT_CONFIG(opengl)
GLuint textureId() const override;
+ QPlatformTextureList::Flags textureListFlags() override;
QImage grabFramebuffer() override;
#else
QImage grabFramebuffer();
diff --git a/tests/auto/qml/qmlcachegen/data/module.mjs b/tests/auto/qml/qmlcachegen/data/module.mjs
new file mode 100644
index 0000000000..6838766329
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/module.mjs
@@ -0,0 +1,6 @@
+
+import { helper } from "utils.mjs"
+
+export function entry() {
+ return helper()
+}
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/data/utils.mjs b/tests/auto/qml/qmlcachegen/data/utils.mjs
new file mode 100644
index 0000000000..25a1f38709
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/utils.mjs
@@ -0,0 +1,4 @@
+
+export function helper() {
+ return "ok"
+}
diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
index 7bd4414302..1a334b68ce 100644
--- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro
+++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
@@ -15,7 +15,9 @@ RESOURCES += \
data/Enums.qml \
data/componentInItem.qml \
data/jsmoduleimport.qml \
- data/script.mjs
+ data/script.mjs \
+ data/module.mjs \
+ data/utils.mjs
workerscripts_test.files = \
data/worker.js \
@@ -25,7 +27,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 102acf73d6..5d87c319f3 100644
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
@@ -65,6 +65,7 @@ private slots:
void qrcScriptImport();
void fsScriptImport();
void moduleScriptImport();
+ void esModulesViaQJSEngine();
void enums();
@@ -360,7 +361,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;
@@ -387,12 +388,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);
@@ -414,7 +411,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"));
@@ -503,7 +500,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());
@@ -584,7 +581,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);
@@ -605,6 +602,14 @@ void tst_qmlcachegen::moduleScriptImport()
}
}
+void tst_qmlcachegen::esModulesViaQJSEngine()
+{
+ QJSEngine engine;
+ QJSValue module = engine.importModule(":/data/module.mjs");
+ QJSValue result = module.property("entry").call();
+ QCOMPARE(result.toString(), "ok");
+}
+
void tst_qmlcachegen::enums()
{
QQmlEngine engine;
@@ -617,7 +622,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(
@@ -632,8 +637,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/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/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..00cda191cc
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
@@ -0,0 +1,16 @@
+import QtQuick.tooling 1.2
+Module {
+ dependencies: []
+ Component {
+ name: "SomethingEntirelyStrange"
+ prototype: "QObject"
+ Enum {
+ name: "AnEnum"
+ values: {
+ "AAA": 0,
+ "BBB": 1,
+ "CCC": 2
+ }
+ }
+ }
+}
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/UnmatchedSignalHandler.qml b/tests/auto/qml/qmllint/data/UnmatchedSignalHandler.qml
new file mode 100644
index 0000000000..064444e182
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/UnmatchedSignalHandler.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/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/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/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index 582f146dca..04f554ac48 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 cleanQmlCode_data();
+ void cleanQmlCode();
+
+ void dirtyQmlCode_data();
+ void dirtyQmlCode();
+
void testUnqualifiedNoSpuriousParentWarning();
- void catchIdentifierNoFalsePositive();
+
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,97 @@ 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()
{
- 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("spuriousParentWarning.qml", true);
+ 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("UnmatchedSignalHandler")
+ << QStringLiteral("UnmatchedSignalHandler.qml")
+ << QString("Warning: no matching signal found for handler \"onClicked\" at 12:13")
+ << QStringLiteral("onMouseXChanged");
}
-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");
+}
+
+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 cae833cd60..79a73299a4 100644
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
@@ -130,6 +130,8 @@ void tst_qmlmin::initTestCase()
invalidFiles << "tests/auto/qml/qjsengine/script/com/trolltech/syntaxerror/__init__.js";
invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
+ invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml";
+ invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.3.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/qqmlbinding/data/noUnexpectedStringConversion.qml b/tests/auto/qml/qqmlbinding/data/noUnexpectedStringConversion.qml
new file mode 100644
index 0000000000..d0f30c5da5
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/noUnexpectedStringConversion.qml
@@ -0,0 +1,30 @@
+import QtQuick 2.12
+import QtQuick.Window 2.12
+
+Window {
+visible: true
+width: 640
+height: 480
+title: qsTr("Hello World")
+
+ Rectangle {
+ id: colorRect
+ objectName: "colorRect"
+ anchors.fill: parent
+ Text {
+ objectName: "colorLabel"
+ id: colorLabel
+ }
+ }
+
+ Binding {
+ target: colorLabel
+ property: "text"
+ value: "red"
+ }
+ Binding {
+ target: colorRect
+ property: "color"
+ value: "red"
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index 9b66cd828a..2c2d311ff7 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -55,6 +55,7 @@ private slots:
void delayed();
void bindingOverwriting();
void bindToQmlComponent();
+ void bindingDoesNoWeirdConversion();
private:
QQmlEngine engine;
@@ -68,7 +69,7 @@ void tst_qqmlbinding::binding()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("test-binding.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QQuickRectangle> rect { qobject_cast<QQuickRectangle*>(c.create()) };
QVERIFY(rect != nullptr);
QQmlBind *binding3 = qobject_cast<QQmlBind*>(rect->findChild<QQmlBind*>("binding3"));
@@ -85,18 +86,16 @@ void tst_qqmlbinding::binding()
QQmlBind *binding = qobject_cast<QQmlBind*>(rect->findChild<QQmlBind*>("binding1"));
QVERIFY(binding != nullptr);
- QCOMPARE(binding->object(), qobject_cast<QObject*>(rect));
+ QCOMPARE(binding->object(), qobject_cast<QObject*>(rect.get()));
QCOMPARE(binding->property(), QLatin1String("text"));
QCOMPARE(binding->value().toString(), QLatin1String("Hello"));
-
- delete rect;
}
void tst_qqmlbinding::whenAfterValue()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("test-binding2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())};
QVERIFY(rect != nullptr);
QCOMPARE(rect->color(), QColor("yellow"));
@@ -104,15 +103,13 @@ void tst_qqmlbinding::whenAfterValue()
rect->setProperty("changeColor", true);
QCOMPARE(rect->color(), QColor("red"));
-
- delete rect;
}
void tst_qqmlbinding::restoreBinding()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("restoreBinding.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QQuickRectangle> rect { qobject_cast<QQuickRectangle*>(c.create()) };
QVERIFY(rect != nullptr);
QQuickRectangle *myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem"));
@@ -134,8 +131,6 @@ void tst_qqmlbinding::restoreBinding()
//original binding restored
myItem->setY(49);
QCOMPARE(myItem->x(), qreal(100-49));
-
- delete rect;
}
void tst_qqmlbinding::restoreBindingValue()
@@ -214,7 +209,7 @@ void tst_qqmlbinding::restoreBindingWithLoop()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("restoreBindingWithLoop.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())};
QVERIFY(rect != nullptr);
QQuickRectangle *myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem"));
@@ -242,15 +237,13 @@ void tst_qqmlbinding::restoreBindingWithLoop()
myItem->setY(49);
QCOMPARE(myItem->x(), qreal(49 + 100));
-
- delete rect;
}
void tst_qqmlbinding::restoreBindingWithoutCrash()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("restoreBindingWithoutCrash.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())};
QVERIFY(rect != nullptr);
QQuickRectangle *myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem"));
@@ -281,8 +274,6 @@ void tst_qqmlbinding::restoreBindingWithoutCrash()
//original binding restored
myItem->setY(49);
QCOMPARE(myItem->x(), qreal(100-49));
-
- delete rect;
}
//QTBUG-20692
@@ -290,15 +281,13 @@ void tst_qqmlbinding::deletedObject()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("deletedObject.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())};
QVERIFY(rect != nullptr);
QGuiApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
//don't crash
rect->setProperty("activateBinding", true);
-
- delete rect;
}
void tst_qqmlbinding::warningOnUnknownProperty()
@@ -307,9 +296,8 @@ void tst_qqmlbinding::warningOnUnknownProperty()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("unknownProperty.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) };
QVERIFY(item);
- delete item;
QCOMPARE(messageHandler.messages().count(), 1);
@@ -323,9 +311,8 @@ void tst_qqmlbinding::warningOnReadOnlyProperty()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("readonlyProperty.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) };
QVERIFY(item);
- delete item;
QCOMPARE(messageHandler.messages().count(), 1);
@@ -339,9 +326,8 @@ void tst_qqmlbinding::disabledOnUnknownProperty()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("disabledUnknown.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) };
QVERIFY(item);
- delete item;
QCOMPARE(messageHandler.messages().count(), 0);
}
@@ -352,10 +338,8 @@ void tst_qqmlbinding::disabledOnReadonlyProperty()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("disabledReadonly.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) };
QVERIFY(item);
- delete item;
-
QCOMPARE(messageHandler.messages().count(), 0);
}
@@ -363,21 +347,19 @@ void tst_qqmlbinding::delayed()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("delayed.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())};
QVERIFY(item != nullptr);
// update on creation
QCOMPARE(item->property("changeCount").toInt(), 1);
- QMetaObject::invokeMethod(item, "updateText");
+ QMetaObject::invokeMethod(item.get(), "updateText");
// doesn't update immediately
QCOMPARE(item->property("changeCount").toInt(), 1);
QCoreApplication::processEvents();
// only updates once (non-delayed would update twice)
QCOMPARE(item->property("changeCount").toInt(), 2);
-
- delete item;
}
void tst_qqmlbinding::bindingOverwriting()
@@ -387,9 +369,8 @@ void tst_qqmlbinding::bindingOverwriting()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("bindingOverwriting.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())};
QVERIFY(item);
- delete item;
QLoggingCategory::setFilterRules(QString());
QCOMPARE(messageHandler.messages().count(), 2);
@@ -402,6 +383,21 @@ void tst_qqmlbinding::bindToQmlComponent()
QVERIFY(c.create());
}
+// QTBUG-78943
+void tst_qqmlbinding::bindingDoesNoWeirdConversion()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("noUnexpectedStringConversion.qml"));
+ QScopedPointer<QObject> o {c.create()};
+ QVERIFY(o);
+ QObject *colorRect = o->findChild<QObject*>("colorRect");
+ QVERIFY(colorRect);
+ QCOMPARE(qvariant_cast<QColor>(colorRect->property("color")), QColorConstants::Red);
+ QObject *colorLabel = o->findChild<QObject*>("colorLabel");
+ QCOMPARE(colorLabel->property("text").toString(), QLatin1String("red"));
+ QVERIFY(colorLabel);
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"
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/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/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 79ec507388..2acc62ca28 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:
@@ -222,12 +225,12 @@ void tst_qqmlcomponent::qmlCreateObjectAutoParent()
QVERIFY(window_item);
QVERIFY(window_window);
- QCOMPARE(qtobject_item->metaObject()->className(), "QQuickItem");
- QCOMPARE(qtobject_window->metaObject()->className(), "QQuickWindow");
- QCOMPARE(item_item->metaObject()->className(), "QQuickItem");
- QCOMPARE(item_window->metaObject()->className(), "QQuickWindow");
- QCOMPARE(window_item->metaObject()->className(), "QQuickItem");
- QCOMPARE(window_window->metaObject()->className(), "QQuickWindow");
+ QVERIFY(QByteArray(qtobject_item->metaObject()->className()).startsWith("QQuickItem"));
+ QVERIFY(QByteArray(qtobject_window->metaObject()->className()).startsWith("QQuickWindow"));
+ QVERIFY(QByteArray(item_item->metaObject()->className()).startsWith("QQuickItem"));
+ QVERIFY(QByteArray(item_window->metaObject()->className()).startsWith("QQuickWindow"));
+ QVERIFY(QByteArray(window_item->metaObject()->className()).startsWith("QQuickItem"));
+ QVERIFY(QByteArray(window_window->metaObject()->className()).startsWith("QQuickWindow"));
QCOMPARE(qtobject_qtobject->parent(), qtobjectParent);
QCOMPARE(qtobject_item->parent(), qtobjectParent);
@@ -668,35 +671,80 @@ void tst_qqmlcomponent::setDataNoEngineNoSegfault()
QVERIFY(!c);
}
-void tst_qqmlcomponent::testSetInitialProperties()
+void tst_qqmlcomponent::testRequiredProperties_data()
+{
+ 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";
+}
+
+
+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 +776,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 +797,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/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
index cf0f3c7bb3..07af519a3d 100644
--- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
+++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
@@ -470,7 +470,7 @@ void tst_qqmlconnections::noAcceleratedGlobalLookup()
QVERIFY(c.isReady());
QScopedPointer<QObject> object(c.create());
const QVariant val = object->property("testEnum");
- QCOMPARE(val.type(), int(QMetaType::Int));
+ QCOMPARE(val.type(), QVariant::Int);
QCOMPARE(val.toInt(), int(Proxy::EnumValue));
}
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/qqmlcpputils/tst_qqmlcpputils.cpp b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
index 99cabb4b09..13e4d4c53b 100644
--- a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
+++ b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
@@ -71,7 +71,7 @@ void tst_qqmlcpputils::fastConnect()
{
MyObject obj;
- qmlobject_connect(&obj, MyObject, SIGNAL(signal1()), &obj, MyObject, SLOT(slot1()))
+ qmlobject_connect(&obj, MyObject, SIGNAL(signal1()), &obj, MyObject, SLOT(slot1()));
obj.signal1();
QCOMPARE(obj.slotCount, 1);
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml
new file mode 100644
index 0000000000..6686831e1c
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml
@@ -0,0 +1,12 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ // QTBUG-78996
+ dateProperty = new Date(2019, 9, 3)
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 9
+ && dateProperty.getDate() == 3)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml
new file mode 100644
index 0000000000..29ec40ffbd
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2019, 2, 0) // Feb 28th
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 1
+ && dateProperty.getDate() == 28)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml
new file mode 100644
index 0000000000..7fc8bf43bd
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2019, 1, 29) // March 1st
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 2
+ && dateProperty.getDate() == 1)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml
new file mode 100644
index 0000000000..6dd84810e6
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2020, 2, 0) // Feb 29th
+ boolProperty = (dateProperty.getFullYear() == 2020
+ && dateProperty.getMonth() == 1
+ && dateProperty.getDate() == 29)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml
new file mode 100644
index 0000000000..ddb79727ef
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2017, 40, -61) // 2020, Feb 29th
+ boolProperty = (dateProperty.getFullYear() == 2020
+ && dateProperty.getMonth() == 1
+ && dateProperty.getDate() == 29)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml
new file mode 100644
index 0000000000..90514c39c8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2019, 12, 0) // Dec 31
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 11
+ && dateProperty.getDate() == 31)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml
new file mode 100644
index 0000000000..c97076f887
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml
@@ -0,0 +1,16 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ // QTBUG-78996
+ dateTimeProperty = new Date(2019, 9, 3, 12)
+ boolProperty = (dateTimeProperty.getFullYear() == 2019
+ && dateTimeProperty.getMonth() == 9
+ && dateTimeProperty.getDate() == 3
+ && dateTimeProperty.getHours() == 12
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml
new file mode 100644
index 0000000000..2b6b9af3e1
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2019, 1, 28, 23, 59, 59, 1001) // 2019-3-1 0:0:0.001
+ boolProperty = (dateTimeProperty.getFullYear() == 2019
+ && dateTimeProperty.getMonth() == 2
+ && dateTimeProperty.getDate() == 1
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 1)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml
new file mode 100644
index 0000000000..7d018e2904
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2019, 11, 31, 1440) // 2020-2-29 0:0:0
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml
new file mode 100644
index 0000000000..0a7687c669
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2020, 2, 1, 0, 0, 0, -1) // 2020-2-29 23:59:59.999
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 23
+ && dateTimeProperty.getMinutes() == 59
+ && dateTimeProperty.getSeconds() == 59
+ && dateTimeProperty.getMilliseconds() == 999)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml
new file mode 100644
index 0000000000..738d603b4b
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2020, 1, 28, 0, 1440) // 2020-2-29 0:0:0
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml
new file mode 100644
index 0000000000..d48534f0d0
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2020, 1, 28, 23, 0, 3600) // 2020-2-29 0:0:0
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml
index 54d29dfc94..9fdb7f92f3 100644
--- a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml
+++ b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml
@@ -1,4 +1,5 @@
import Qt.test 1.0
+import QtQuick 2.0 // We need the the QtQuick color provider for colorProperty
MyQmlObject
{
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index 730dc7cab8..3233e7f105 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -1098,13 +1098,11 @@ class MyItemUsingRevisionedObject : public QObject
Q_PROPERTY(MyRevisionedClass *revisioned READ revisioned)
public:
- MyItemUsingRevisionedObject() {
- m_revisioned = new MyRevisionedClass;
- }
+ MyItemUsingRevisionedObject() : m_revisioned (new MyRevisionedClass) {}
- MyRevisionedClass *revisioned() const { return m_revisioned; }
+ MyRevisionedClass *revisioned() const { return m_revisioned.get(); }
private:
- MyRevisionedClass *m_revisioned;
+ QScopedPointer<MyRevisionedClass> m_revisioned;
};
QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered)
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 269d90c891..f4de83eb87 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -79,6 +79,10 @@ private slots:
void assignDate();
void exportDate_data();
void exportDate();
+ void checkDate_data();
+ void checkDate();
+ void checkDateTime_data();
+ void checkDateTime();
void idShortcutInvalidates();
void boolPropertiesEvaluateAsBool();
void methods();
@@ -568,6 +572,82 @@ void tst_qqmlecmascript::exportDate()
QCOMPARE(object->boolProperty(), true);
}
+void tst_qqmlecmascript::checkDate_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<QDate>("date");
+ // NB: JavaScript month-indices are Jan = 0 to Dec = 11; QDate's are Jan = 1 to Dec = 12.
+ QTest::newRow("denormal-March")
+ << testFileUrl("checkDate-denormal-March.qml")
+ << QDate(2019, 3, 1);
+ QTest::newRow("denormal-leap")
+ << testFileUrl("checkDate-denormal-leap.qml")
+ << QDate(2020, 2, 29);
+ QTest::newRow("denormal-Feb")
+ << testFileUrl("checkDate-denormal-Feb.qml")
+ << QDate(2019, 2, 28);
+ QTest::newRow("denormal-year")
+ << testFileUrl("checkDate-denormal-year.qml")
+ << QDate(2019, 12, 31);
+ QTest::newRow("denormal-wrap")
+ << testFileUrl("checkDate-denormal-wrap.qml")
+ << QDate(2020, 2, 29);
+ QTest::newRow("October")
+ << testFileUrl("checkDate-October.qml")
+ << QDate(2019, 10, 3);
+}
+
+void tst_qqmlecmascript::checkDate()
+{
+ QFETCH(const QUrl, source);
+ QFETCH(const QDate, date);
+ QQmlEngine e;
+ QQmlComponent component(&e, source);
+ QScopedPointer<QObject> obj(component.create());
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data());
+ QVERIFY(object != nullptr);
+ QCOMPARE(object->dateProperty(), date);
+ QVERIFY(object->boolProperty());
+}
+
+void tst_qqmlecmascript::checkDateTime_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<QDateTime>("when");
+ // NB: JavaScript month-indices are Jan = 0 to Dec = 11; QDate's are Jan = 1 to Dec = 12.
+ QTest::newRow("denormal-March")
+ << testFileUrl("checkDateTime-denormal-March.qml")
+ << QDateTime(QDate(2019, 3, 1), QTime(0, 0, 0, 1), Qt::LocalTime);
+ QTest::newRow("denormal-leap")
+ << testFileUrl("checkDateTime-denormal-leap.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(23, 59, 59, 999), Qt::LocalTime);
+ QTest::newRow("denormal-hours")
+ << testFileUrl("checkDateTime-denormal-hours.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime);
+ QTest::newRow("denormal-minutes")
+ << testFileUrl("checkDateTime-denormal-minutes.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime);
+ QTest::newRow("denormal-seconds")
+ << testFileUrl("checkDateTime-denormal-seconds.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime);
+ QTest::newRow("October")
+ << testFileUrl("checkDateTime-October.qml")
+ << QDateTime(QDate(2019, 10, 3), QTime(12, 0), Qt::LocalTime);
+}
+
+void tst_qqmlecmascript::checkDateTime()
+{
+ QFETCH(const QUrl, source);
+ QFETCH(const QDateTime, when);
+ QQmlEngine e;
+ QQmlComponent component(&e, source);
+ QScopedPointer<QObject> obj(component.create());
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data());
+ QVERIFY(object != nullptr);
+ QCOMPARE(object->dateTimeProperty(), when);
+ QVERIFY(object->boolProperty());
+}
+
void tst_qqmlecmascript::idShortcutInvalidates()
{
QQmlEngine engine;
@@ -1693,10 +1773,10 @@ void tst_qqmlecmascript::componentCreation()
}
QQmlComponent component(&engine, testUrl);
- MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
+ QScopedPointer<MyTypeObject> object(qobject_cast<MyTypeObject*>(component.create()));
QVERIFY(object != nullptr);
- QMetaObject::invokeMethod(object, method.toUtf8());
+ QMetaObject::invokeMethod(object.get(), method.toUtf8());
QQmlComponent *created = object->componentProperty();
if (creationError.isEmpty()) {
@@ -1704,7 +1784,7 @@ void tst_qqmlecmascript::componentCreation()
QObject *expectedParent = reinterpret_cast<QObject *>(quintptr(-1));
if (createdParent == QLatin1String("obj")) {
- expectedParent = object;
+ expectedParent = object.get();
} else if ((createdParent == QLatin1String("null")) || createdParent.isEmpty()) {
expectedParent = nullptr;
}
@@ -2050,7 +2130,7 @@ void tst_qqmlecmascript::functionErrors()
QObject *resource = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
warning = url + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function");
- warning = warning.arg(QString::number((quintptr)resource, 16));
+ warning = warning.arg(QString::number(quintptr(resource), 16));
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
delete object;
@@ -3124,13 +3204,13 @@ void tst_qqmlecmascript::callQtInvokables()
void tst_qqmlecmascript::resolveClashingProperties()
{
- ClashingNames *o = new ClashingNames();
+ QScopedPointer<ClashingNames> o(new ClashingNames());
QQmlEngine qmlengine;
QV4::ExecutionEngine *engine = qmlengine.handle();
QV4::Scope scope(engine);
- QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o));
+ QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o.get()));
QV4::ObjectIterator it(scope, object->as<QV4::Object>(), QV4::ObjectIterator::EnumerableOnly);
QV4::ScopedValue name(scope);
QV4::ScopedValue value(scope);
@@ -4575,7 +4655,7 @@ void tst_qqmlecmascript::scarceResources_other()
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
expectedWarning = varComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function");
- expectedWarning = expectedWarning.arg(QString::number((quintptr)eo, 16));
+ expectedWarning = expectedWarning.arg(QString::number(quintptr(eo), 16));
QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
@@ -4649,7 +4729,7 @@ void tst_qqmlecmascript::scarceResources_other()
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
expectedWarning = variantComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function");
- expectedWarning = expectedWarning.arg(QString::number((quintptr)eo, 16));
+ expectedWarning = expectedWarning.arg(QString::number(quintptr(eo), 16));
QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
@@ -6093,7 +6173,7 @@ void tst_qqmlecmascript::variants()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("variants.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QCOMPARE(object->property("undefinedVariant").type(), QVariant::Invalid);
@@ -6102,13 +6182,13 @@ void tst_qqmlecmascript::variants()
QCOMPARE(object->property("doubleVariant").type(), QVariant::Double);
QVariant result;
- QMetaObject::invokeMethod(object, "checkNull", Q_RETURN_ARG(QVariant, result));
+ QMetaObject::invokeMethod(object.get(), "checkNull", Q_RETURN_ARG(QVariant, result));
QCOMPARE(result.toBool(), true);
- QMetaObject::invokeMethod(object, "checkUndefined", Q_RETURN_ARG(QVariant, result));
+ QMetaObject::invokeMethod(object.get(), "checkUndefined", Q_RETURN_ARG(QVariant, result));
QCOMPARE(result.toBool(), true);
- QMetaObject::invokeMethod(object, "checkNumber", Q_RETURN_ARG(QVariant, result));
+ QMetaObject::invokeMethod(object.get(), "checkNumber", Q_RETURN_ARG(QVariant, result));
QCOMPARE(result.toBool(), true);
}
@@ -6357,6 +6437,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
@@ -6998,12 +7080,12 @@ void tst_qqmlecmascript::realToInt()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("realToInt.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
- QMetaObject::invokeMethod(object, "test1");
+ QMetaObject::invokeMethod(object.get(), "test1");
QCOMPARE(object->value(), int(4));
- QMetaObject::invokeMethod(object, "test2");
+ QMetaObject::invokeMethod(object.get(), "test2");
QCOMPARE(object->value(), int(7));
}
@@ -7012,7 +7094,7 @@ void tst_qqmlecmascript::urlProperty()
QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("urlProperty.1.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
object->setStringProperty("http://qt-project.org");
QCOMPARE(object->urlProperty(), QUrl("http://qt-project.org/index.html"));
@@ -7027,7 +7109,7 @@ void tst_qqmlecmascript::urlPropertyWithEncoding()
QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("urlProperty.2.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
object->setStringProperty("http://qt-project.org");
const QUrl encoded = QUrl::fromEncoded("http://qt-project.org/?get%3cDATA%3e", QUrl::TolerantMode);
@@ -7062,7 +7144,7 @@ void tst_qqmlecmascript::dynamicString()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("dynamicString.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QCOMPARE(object->property("stringProperty").toString(),
QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
@@ -7072,7 +7154,7 @@ void tst_qqmlecmascript::deleteLaterObjectMethodCall()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deleteLaterObjectMethodCall.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
@@ -7080,7 +7162,7 @@ void tst_qqmlecmascript::automaticSemicolon()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("automaticSemicolon.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
@@ -7088,7 +7170,7 @@ void tst_qqmlecmascript::compatibilitySemicolon()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("compatibilitySemicolon.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
@@ -7096,7 +7178,7 @@ void tst_qqmlecmascript::incrDecrSemicolon1()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon1.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
@@ -7104,7 +7186,7 @@ void tst_qqmlecmascript::incrDecrSemicolon2()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon2.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
@@ -7120,7 +7202,7 @@ void tst_qqmlecmascript::unaryExpression()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("unaryExpression.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
@@ -7260,7 +7342,7 @@ void tst_qqmlecmascript::switchStatement()
QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("switchStatement.1.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
// `object->value()' is the number of executed statements
@@ -7283,7 +7365,7 @@ void tst_qqmlecmascript::switchStatement()
{
QQmlComponent component(&engine, testFileUrl("switchStatement.2.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
// `object->value()' is the number of executed statements
@@ -7306,7 +7388,7 @@ void tst_qqmlecmascript::switchStatement()
{
QQmlComponent component(&engine, testFileUrl("switchStatement.3.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
// `object->value()' is the number of executed statements
@@ -7333,7 +7415,7 @@ void tst_qqmlecmascript::switchStatement()
QString warning = component.url().toString() + ":4:5: Unable to assign [undefined] to int";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
// `object->value()' is the number of executed statements
@@ -7357,7 +7439,7 @@ void tst_qqmlecmascript::switchStatement()
{
QQmlComponent component(&engine, testFileUrl("switchStatement.5.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
// `object->value()' is the number of executed statements
@@ -7380,7 +7462,7 @@ void tst_qqmlecmascript::switchStatement()
{
QQmlComponent component(&engine, testFileUrl("switchStatement.6.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
// `object->value()' is the number of executed statements
@@ -7408,7 +7490,7 @@ void tst_qqmlecmascript::withStatement()
{
QUrl url = testFileUrl("withStatement.1.qml");
QQmlComponent component(&engine, url);
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
QCOMPARE(object->value(), 123);
@@ -7420,7 +7502,7 @@ void tst_qqmlecmascript::tryStatement()
QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("tryStatement.1.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
QCOMPARE(object->value(), 123);
@@ -7428,7 +7510,7 @@ void tst_qqmlecmascript::tryStatement()
{
QQmlComponent component(&engine, testFileUrl("tryStatement.2.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
QCOMPARE(object->value(), 321);
@@ -7436,7 +7518,7 @@ void tst_qqmlecmascript::tryStatement()
{
QQmlComponent component(&engine, testFileUrl("tryStatement.3.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
QVERIFY(object->qjsvalue().isUndefined());
@@ -7444,7 +7526,7 @@ void tst_qqmlecmascript::tryStatement()
{
QQmlComponent component(&engine, testFileUrl("tryStatement.4.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create()));
QVERIFY(object != nullptr);
QVERIFY(object->qjsvalue().isUndefined());
@@ -7585,7 +7667,7 @@ void tst_qqmlecmascript::onDestruction()
// component instance. This shouldn't crash.
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("onDestruction.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
QVERIFY(obj != nullptr);
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
}
@@ -7926,19 +8008,19 @@ void tst_qqmlecmascript::dateParse()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("date.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
if (object == nullptr)
qDebug() << component.errorString();
QVERIFY(object != nullptr);
QVariant q;
- QMetaObject::invokeMethod(object, "test_is_invalid_jsDateTime", Q_RETURN_ARG(QVariant, q));
+ QMetaObject::invokeMethod(object.get(), "test_is_invalid_jsDateTime", Q_RETURN_ARG(QVariant, q));
QVERIFY(q.toBool());
- QMetaObject::invokeMethod(object, "test_is_invalid_qtDateTime", Q_RETURN_ARG(QVariant, q));
+ QMetaObject::invokeMethod(object.get(), "test_is_invalid_qtDateTime", Q_RETURN_ARG(QVariant, q));
QVERIFY(q.toBool());
- QMetaObject::invokeMethod(object, "test_rfc2822_date", Q_RETURN_ARG(QVariant, q));
+ QMetaObject::invokeMethod(object.get(), "test_rfc2822_date", Q_RETURN_ARG(QVariant, q));
QCOMPARE(q.toLongLong(), 1379512851000LL);
}
@@ -7947,14 +8029,14 @@ void tst_qqmlecmascript::utcDate()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("utcdate.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
if (object == nullptr)
qDebug() << component.errorString();
QVERIFY(object != nullptr);
QVariant q;
QVariant val = QString::fromLatin1("2014-07-16T23:30:31");
- QMetaObject::invokeMethod(object, "check_utc", Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, val));
+ QMetaObject::invokeMethod(object.get(), "check_utc", Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, val));
QVERIFY(q.toBool());
}
@@ -7963,20 +8045,20 @@ void tst_qqmlecmascript::negativeYear()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("negativeyear.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
if (object == nullptr)
qDebug() << component.errorString();
QVERIFY(object != nullptr);
QVariant q;
- QMetaObject::invokeMethod(object, "check_negative_tostring", Q_RETURN_ARG(QVariant, q));
+ QMetaObject::invokeMethod(object.get(), "check_negative_tostring", Q_RETURN_ARG(QVariant, q));
// Only check for the year. We hope that every language writes the year in arabic numerals and
// in relation to a specific dude's date of birth. We also hope that no language adds a "-2001"
// junk string somewhere in the middle.
QVERIFY(q.toString().indexOf(QStringLiteral("-2001")) != -1);
- QMetaObject::invokeMethod(object, "check_negative_toisostring", Q_RETURN_ARG(QVariant, q));
+ QMetaObject::invokeMethod(object.get(), "check_negative_toisostring", Q_RETURN_ARG(QVariant, q));
QCOMPARE(q.toString().left(16), QStringLiteral("result: -002000-"));
}
@@ -8019,6 +8101,7 @@ void tst_qqmlecmascript::jsOwnedObjectsDeletedOnEngineDestroy()
QCOMPARE(spy1.count(), 1);
QCOMPARE(spy2.count(), 1);
+ deleteObject.deleteNestedObject();
delete object;
}
@@ -8030,7 +8113,7 @@ void tst_qqmlecmascript::updateCall()
QString file("updateCall.qml");
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl(file));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
@@ -8041,7 +8124,7 @@ void tst_qqmlecmascript::numberParsing()
QString file("numberParsing.%1.qml");
file = file.arg(i);
QQmlComponent component(&engine, testFileUrl(file));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
}
for (int i = 1; i < 3; ++i) {
@@ -8224,8 +8307,8 @@ void tst_qqmlecmascript::idsAsLValues()
QString err = QString(QLatin1String("%1:5: Error: left-hand side of assignment operator is not an lvalue")).arg(testFileUrl("idAsLValue.qml").toString());
QQmlComponent component(&engine, testFileUrl("idAsLValue.qml"));
QTest::ignoreMessage(QtWarningMsg, qPrintable(err));
- MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
- QVERIFY(!object);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!qobject_cast<MyQmlObject*>(object.get()));
}
void tst_qqmlecmascript::qtbug_34792()
@@ -8440,10 +8523,10 @@ void tst_qqmlecmascript::readUnregisteredQObjectProperty()
qmlRegisterType<ObjectContainer>("Test", 1, 0, "ObjectContainer");
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("accessUnregisteredQObjectProperty.qml"));
- QObject *root = component.create();
+ QScopedPointer<QObject> root(component.create());
QVERIFY(root);
- QMetaObject::invokeMethod(root, "readProperty");
+ QMetaObject::invokeMethod(root.get(), "readProperty");
QCOMPARE(root->property("container").value<ObjectContainer*>()->mGetterCalled, true);
}
@@ -8452,10 +8535,10 @@ void tst_qqmlecmascript::writeUnregisteredQObjectProperty()
qmlRegisterType<ObjectContainer>("Test", 1, 0, "ObjectContainer");
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("accessUnregisteredQObjectProperty.qml"));
- QObject *root = component.create();
+ QScopedPointer<QObject> root(component.create());
QVERIFY(root);
- QMetaObject::invokeMethod(root, "writeProperty");
+ QMetaObject::invokeMethod(root.get(), "writeProperty");
QCOMPARE(root->property("container").value<ObjectContainer*>()->mSetterCalled, true);
}
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/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index aae42e9ebb..2a3b945509 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -424,12 +424,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);
}
@@ -511,6 +512,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());
@@ -601,11 +603,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());
@@ -616,13 +617,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());
}
@@ -772,6 +773,7 @@ public:
};
Q_DECLARE_METATYPE(QList<QQmlAbstractUrlInterceptor::DataType>);
+
void tst_qqmlengine::urlInterceptor_data()
{
QTest::addColumn<QUrl>("testFile");
@@ -940,14 +942,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"
@@ -1107,6 +1110,16 @@ void tst_qqmlengine::singletonInstance()
SomeQObjectClass * instance = engine.singletonInstance<SomeQObjectClass*>(cppSingletonTypeId);
QVERIFY(!instance);
}
+
+ {
+ // deleted object
+ auto dayfly = new QObject{};
+ 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.");
+ QObject *instance = engine.singletonInstance<QObject*>(id);
+ QVERIFY(!instance);
+ }
}
void tst_qqmlengine::aggressiveGc()
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..756b3b1d7c 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;
@@ -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/alias.17.qml b/tests/auto/qml/qqmllanguage/data/alias.17.qml
new file mode 100644
index 0000000000..a76dd120b6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/alias.17.qml
@@ -0,0 +1,31 @@
+import QtQuick 2.12
+
+Item {
+ id: root
+ anchors.fill: parent
+ width: 100
+ height: 100
+ property bool success: checkValue === aliasUser.topMargin
+ property int checkValue: 42
+ Rectangle {
+ id: myItem
+ objectName: "myItem"
+ color: "blue"
+ anchors.topMargin: root.checkValue
+ width: 50
+ height: 50
+ Text {text: "source:\n" + myItem.anchors.topMargin}
+ }
+
+ Rectangle {
+ property alias topMargin: myItem.anchors.topMargin
+ id: aliasUser
+ objectName: "aliasUser"
+ color: "red"
+ anchors.left: myItem.right
+ width: 50
+ height: 50
+ Text {objectName: "myText"; text: "alias:\n" + aliasUser.topMargin}
+ }
+}
+
diff --git a/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt
index 30748234bc..5a144f2db5 100644
--- a/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt
@@ -1 +1 @@
-3:5:Invalid grouped property access
+3:5:Invalid grouped property access: Property "value" with primitive type "int".
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/fuzzed.2.errors.txt b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt
index 92ce4c649f..8dca84b34e 100644
--- a/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt
@@ -1,2 +1 @@
5:1:TetZ$ is not a type
--1:-1:Invalid QML type name "TetZ$"
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt
index 810fd31b41..5deec4ccf9 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt
@@ -1 +1 @@
-5:5:Invalid grouped property access
+5:5:Invalid grouped property access: Property "o" with primitive type "int".
diff --git a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
index 945dacf8ab..043f714636 100644
--- a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
@@ -1 +1 @@
-4:18:Can not assign value of type "int" to property "x", expecting an object
+4:18:Can not assign value of type "MyTypeObject" to property "x", expecting "int"
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..534322215f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.13
+Item {
+ default required property int test // cannot have required default property
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 6956533196..462745eb93 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,8 @@ void registerTypes()
qmlRegisterType<LazyDeferredSubObject>("Test", 1, 0, "LazyDeferredSubObject");
qmlRegisterType<DeferredProperties>("Test", 1, 0, "DeferredProperties");
+
+ qmlRegisterTypesAndRevisions<Extended, Foreign, ForeignExtended>("Test", 1);
}
QVariant myCustomVariantTypeConverter(const QString &data)
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 1aab24841a..bfbd3e66f5 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1420,6 +1420,40 @@ 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 Foreign
+{
+ Q_GADGET
+ QML_FOREIGN(QObject)
+ QML_NAMED_ELEMENT(Foreign)
+};
+
+class ForeignExtended
+{
+ Q_GADGET
+ QML_FOREIGN(QObject)
+ QML_NAMED_ELEMENT(ForeignExtended)
+ QML_EXTENDED(Extension)
+};
void registerTypes();
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 8adacd8829..e2032c3b86 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -132,6 +132,7 @@ private slots:
void autoComponentCreation();
void autoComponentCreationInGroupProperty();
void propertyValueSource();
+ void requiredProperty();
void attachedProperties();
void dynamicObjects();
void customVariantTypes();
@@ -243,12 +244,11 @@ private slots:
void compositeSingletonModuleQualified();
void compositeSingletonInstantiateError();
void compositeSingletonDynamicPropertyError();
- void compositeSingletonDynamicSignal();
+ void compositeSingletonDynamicSignalAndJavaScriptPragma();
void compositeSingletonQmlRegisterTypeError();
void compositeSingletonQmldirNoPragmaError();
void compositeSingletonQmlDirError();
void compositeSingletonRemote();
- void compositeSingletonJavaScriptPragma();
void compositeSingletonSelectors();
void compositeSingletonRegistered();
void compositeSingletonCircular();
@@ -304,6 +304,8 @@ private slots:
void typeWrapperToVariant();
+ void extendedForeignTypes();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -1634,6 +1636,25 @@ 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.3.qml"));
+ QVERIFY(!component.errors().empty());
+ }
+}
+
void tst_qqmllanguage::attachedProperties()
{
QQmlComponent component(&engine, testFileUrl("attachedProperties.qml"));
@@ -1970,6 +1991,69 @@ void tst_qqmllanguage::aliasProperties()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
}
+
+ // Alias to grouped property
+ {
+ QQmlComponent component(&engine, testFileUrl("alias.17.qml"));
+ VERIFY_ERRORS(0);
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QVERIFY(object->property("success").toBool());
+ }
+
+ // Alias to grouped property updates
+ {
+ QQmlComponent component(&engine, testFileUrl("alias.17.qml"));
+ VERIFY_ERRORS(0);
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QObject *aliasUser = object->findChild<QObject*>(QLatin1String("aliasUser"));
+ QVERIFY(aliasUser);
+ QQmlProperty checkValueProp(object.get(), "checkValue");
+ QVERIFY(checkValueProp.isValid());
+ checkValueProp.write(777);
+ QCOMPARE(object->property("checkValue").toInt(), 777);
+ QCOMPARE(aliasUser->property("topMargin").toInt(), 777);
+ }
+
+ // Write to alias to grouped property
+ {
+ QQmlComponent component(&engine, testFileUrl("alias.17.qml"));
+ VERIFY_ERRORS(0);
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QObject *aliasUser = object->findChild<QObject*>(QLatin1String("aliasUser"));
+ QVERIFY(aliasUser);
+ QQmlProperty topMarginProp {aliasUser, "topMargin"};
+ QVERIFY(topMarginProp.isValid());
+ topMarginProp.write(777);
+ QObject *myItem = object->findChild<QObject*>(QLatin1String("myItem"));
+ QVERIFY(myItem);
+ auto anchors = myItem->property("anchors").value<QObject*>();
+ QVERIFY(anchors);
+ QCOMPARE(anchors->property("topMargin").toInt(), 777);
+ }
+
+ // Binding to alias to grouped property gets updated
+ {
+ QQmlComponent component(&engine, testFileUrl("alias.17.qml"));
+ VERIFY_ERRORS(0);
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QObject *aliasUser = object->findChild<QObject*>(QLatin1String("aliasUser"));
+ QVERIFY(aliasUser);
+ QQmlProperty topMarginProp {aliasUser, "topMargin"};
+ QVERIFY(topMarginProp.isValid());
+ topMarginProp.write(20);
+ QObject *myText = object->findChild<QObject*>(QLatin1String("myText"));
+ QVERIFY(myText);
+ auto text = myText->property("text").toString();
+ QCOMPARE(text, "alias:\n20");
+ }
}
// QTBUG-13374 Test that alias properties and signals can coexist
@@ -2500,7 +2584,15 @@ void tst_qqmllanguage::testType(const QString& qml, const QString& type, const Q
VERIFY_ERRORS(0);
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QCOMPARE(QString(object->metaObject()->className()), type);
+ const QMetaObject *meta = object->metaObject();
+ for (; meta; meta = meta->superClass()) {
+ const QString className(meta->className());
+ if (!className.contains("_QMLTYPE_") && !className.contains("_QML_")) {
+ QCOMPARE(className, type);
+ break;
+ }
+ }
+ QVERIFY(meta != nullptr);
}
engine.setImportPathList(defaultImportPathList);
@@ -4043,10 +4135,12 @@ void tst_qqmllanguage::implicitImportsLast()
VERIFY_ERRORS(0);
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QVERIFY(QString(object->metaObject()->className()).startsWith(QLatin1String("QQuickMouseArea")));
+ QVERIFY(QString(object->metaObject()->superClass()->superClass()->className())
+ .startsWith(QLatin1String("QQuickMouseArea")));
QObject* object2 = object->property("item").value<QObject*>();
QVERIFY(object2 != nullptr);
- QCOMPARE(QString(object2->metaObject()->className()), QLatin1String("QQuickRectangle"));
+ QCOMPARE(QString(object2->metaObject()->superClass()->className()),
+ QLatin1String("QQuickRectangle"));
engine.setImportPathList(defaultImportPathList);
}
@@ -4267,16 +4361,35 @@ void tst_qqmllanguage::compositeSingletonDynamicPropertyError()
VERIFY_ERRORS(0);
}
-// Having a composite singleton type as dynamic signal parameter succeeds
-// (like C++ singleton)
-void tst_qqmllanguage::compositeSingletonDynamicSignal()
+void tst_qqmllanguage::compositeSingletonDynamicSignalAndJavaScriptPragma()
{
- QQmlComponent component(&engine, testFileUrl("singletonTest11.qml"));
- VERIFY_ERRORS(0);
- QScopedPointer<QObject> o(component.create());
- QVERIFY(o != nullptr);
+ {
+ // Having a composite singleton type as dynamic signal parameter succeeds
+ // (like C++ singleton)
- verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", -55);
+ QQmlComponent component(&engine, testFileUrl("singletonTest11.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o != nullptr);
+
+ verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", -55);
+ }
+ {
+ // Load a composite singleton type and a javascript file that has .pragma library
+ // in it. This will make sure that the javascript .pragma does not get mixed with
+ // the pragma Singleton changes.
+
+ QQmlComponent component(&engine, testFileUrl("singletonTest16.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o != nullptr);
+
+ // The value1 that is read from the SingletonType was changed from 125 to 99
+ // above. As the type is a singleton and
+ // the engine has not been destroyed, we just retrieve the old instance and
+ // the value is still 99.
+ verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", 333);
+ }
}
// Use qmlRegisterType to register a qml composite type with pragma Singleton defined in it.
@@ -4328,23 +4441,6 @@ void tst_qqmllanguage::compositeSingletonRemote()
verifyCompositeSingletonPropertyValues(o.data(), "value1", 525, "value2", 355);
}
-// Load a composite singleton type and a javascript file that has .pragma library
-// in it. This will make sure that the javascript .pragma does not get mixed with
-// the pragma Singleton changes.
-void tst_qqmllanguage::compositeSingletonJavaScriptPragma()
-{
- QQmlComponent component(&engine, testFileUrl("singletonTest16.qml"));
- VERIFY_ERRORS(0);
- QScopedPointer<QObject> o(component.create());
- QVERIFY(o != nullptr);
-
- // The value1 that is read from the SingletonType was changed from 125 to 99
- // in compositeSingletonDynamicSignal() above. As the type is a singleton and
- // the engine has not been destroyed, we just retrieve the old instance and
- // the value is still 99.
- verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", 333);
-}
-
// Reads values from a Singleton accessed through selectors.
void tst_qqmllanguage::compositeSingletonSelectors()
{
@@ -5030,7 +5126,6 @@ void tst_qqmllanguage::instanceof()
if (QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomRectangle") ||
QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomImport.CustomRectangle"))
- QEXPECT_FAIL("", "QTBUG-58477: QML type rules are a little lax", Continue);
QCOMPARE(returnValue, expectedValue.toBool());
} else {
QVERIFY(expr.hasError());
@@ -5066,7 +5161,8 @@ void tst_qqmllanguage::accessDeletedObject()
{
QQmlEngine engine;
- engine.rootContext()->setContextProperty("objectCreator", new ObjectCreator);
+ QScopedPointer<ObjectCreator> creator(new ObjectCreator);
+ engine.rootContext()->setContextProperty("objectCreator", creator.get());
QQmlComponent component(&engine, testFileUrl("accessDeletedObject.qml"));
VERIFY_ERRORS(0);
@@ -5163,6 +5259,21 @@ 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"));
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 77ab0ecbc0..75a932b6f4 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -128,6 +128,8 @@ private slots:
void qobjectTrackerForDynamicModelObjects();
void crash_append_empty_array();
void dynamic_roles_crash_QTBUG_38907();
+ void nestedListModelIteration();
+ void undefinedAppendShouldCauseError();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -1667,6 +1669,61 @@ void tst_qqmllistmodel::dynamic_roles_crash_QTBUG_38907()
QVERIFY(retVal.toBool());
}
+void tst_qqmllistmodel::nestedListModelIteration()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg ,R"({"subItems":[{"a":1,"b":0,"c":0},{"a":0,"b":2,"c":0},{"a":0,"b":0,"c":3}]})");
+ component.setData(
+ R"(import QtQuick 2.5
+ Item {
+ visible: true
+ width: 640
+ height: 480
+ ListModel {
+ id : model
+ }
+ Component.onCompleted: {
+ var tempData = {
+ subItems: [{a: 1}, {b: 2}, {c: 3}]
+ }
+ model.insert(0, tempData)
+ console.log(JSON.stringify(model.get(0)))
+ }
+ })",
+ QUrl());
+ QScopedPointer<QObject>(component.create());
+}
+
+// QTBUG-63569
+void tst_qqmllistmodel::undefinedAppendShouldCauseError()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(
+ R"(import QtQuick 2.5
+ Item {
+ width: 640
+ height: 480
+ ListModel {
+ id : model
+ }
+ Component.onCompleted: {
+ var tempData = {
+ faulty: undefined
+ }
+ model.insert(0, tempData)
+ tempData.faulty = null
+ model.insert(0, tempData)
+ }
+ })",
+ QUrl());
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: faulty is undefined. Adding an object with a undefined member does not create a role for it.");
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: faulty is null. Adding an object with a null member does not create a role for it.");
+ QScopedPointer<QObject>(component.create());
+}
+
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"
diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
index 199f7bc7e4..8efaedf5b5 100644
--- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
+++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
@@ -87,7 +87,7 @@ public:
void tst_qqmllistreference::initTestCase()
{
QQmlDataTest::initTestCase();
- qmlRegisterType<TestType>();
+ qmlRegisterAnonymousType<TestType>("Test", 1);
}
void tst_qqmllistreference::qmllistreference()
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/multiSingleton.qml b/tests/auto/qml/qqmlmoduleplugin/data/multiSingleton.qml
new file mode 100644
index 0000000000..2fc2e9f076
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/multiSingleton.qml
@@ -0,0 +1,6 @@
+import org.qtproject.ModuleWithQmlSingleton 1.0
+import QtQuick 2.0
+
+Item {
+ Component.onCompleted: MySingleton
+}
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml
new file mode 100644
index 0000000000..258667be18
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml
@@ -0,0 +1,17 @@
+pragma Singleton
+import QtQuick 2.0
+import Test 1.0
+
+QtObject {
+ property Loader _loader: Loader {
+ source: "internal/InternalType.qml"
+ }
+
+ Component.onCompleted: {
+ if (Tracker.objectName === "first")
+ Tracker.objectName = "second"
+ else
+ Tracker.objectName = "first"
+ //console.log("created singleton", this)
+ }
+}
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton2.qml b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton2.qml
new file mode 100644
index 0000000000..9be34eb061
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton2.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQuick 2.0
+import org.qtproject.ModuleWithQmlSingleton 1.0
+import "."
+
+QtObject {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/internal/InternalType.qml b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/internal/InternalType.qml
new file mode 100644
index 0000000000..4a8badefd2
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/internal/InternalType.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+import ".."
+
+QtObject {
+ Component.onCompleted: MySingleton
+}
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/moduleWithQmlSingleton.pro b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/moduleWithQmlSingleton.pro
new file mode 100644
index 0000000000..b16e0743c8
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/moduleWithQmlSingleton.pro
@@ -0,0 +1,18 @@
+TEMPLATE = lib
+CONFIG += plugin
+SOURCES = plugin.cpp
+QT = core qml
+DESTDIR = ../imports/org/qtproject/ModuleWithQmlSingleton
+
+QT += core-private gui-private qml-private
+
+IMPORT_FILES = \
+ qmldir \
+ MySingleton.qml \
+ MySingleton2.qml
+
+include (../../../shared/imports.pri)
+
+subfiles.files = internal/InternalType.qml
+subfiles.path = $$DESTDIR/internal
+COPIES += subfiles
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
new file mode 100644
index 0000000000..6329927c34
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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 <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqml.h>
+#include <QDir>
+#include <QDebug>
+
+class MyPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ MyPlugin() {}
+
+ void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == "org.qtproject.ModuleWithQmlSingleton");
+ qmlRegisterSingletonType(baseUrl().resolved(QUrl("ModuleWithQmlSingleton/MySingleton.qml")), uri, 1, 0, "MySingleton");
+ qmlRegisterSingletonType(baseUrl().resolved(QUrl("ModuleWithQmlSingleton/MySingleton2.qml")), uri, 1, 0, "MySingleton2");
+ }
+};
+
+#include "plugin.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/qmldir b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/qmldir
new file mode 100644
index 0000000000..3483f80ab1
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/qmldir
@@ -0,0 +1,2 @@
+module org.qtproject.ModuleWithQmlSingleton
+plugin moduleWithQmlSingleton
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/qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
index ae13a041cc..44b3ab14e6 100644
--- a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
+++ b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
@@ -20,7 +20,8 @@ SUBDIRS =\
plugin/childplugin\
plugin.2/childplugin\
plugin.2.1/childplugin\
- plugin.2.2
+ plugin.2.2\
+ moduleWithQmlSingleton
tst_qqmlmoduleplugin_pro.depends += plugin
SUBDIRS += tst_qqmlmoduleplugin.pro
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index 82aa265465..f15d53d022 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -82,6 +82,7 @@ private slots:
void importsChildPlugin2();
void importsChildPlugin21();
void parallelPluginImport();
+ void multiSingleton();
private:
QString m_importsDirectory;
@@ -627,7 +628,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"
@@ -791,6 +792,20 @@ void tst_qqmlmoduleplugin::parallelPluginImport()
worker.wait();
}
+void tst_qqmlmoduleplugin::multiSingleton()
+{
+ QQmlEngine engine;
+ QObject obj;
+ qmlRegisterSingletonInstance("Test", 1, 0, "Tracker", &obj);
+ engine.addImportPath(m_importsDirectory);
+ QQmlComponent component(&engine, testFileUrl("multiSingleton.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != nullptr);
+ QCOMPARE(obj.objectName(), QLatin1String("first"));
+ delete object;
+}
+
+
QTEST_MAIN(tst_qqmlmoduleplugin)
#include "tst_qqmlmoduleplugin.moc"
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/qqmlpromise/data/promisehandlerthrows.qml b/tests/auto/qml/qqmlpromise/data/promisehandlerthrows.qml
new file mode 100644
index 0000000000..d23ea43e74
--- /dev/null
+++ b/tests/auto/qml/qqmlpromise/data/promisehandlerthrows.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.12
+
+Item {
+ id: root
+ property string errorMessage
+ Component.onCompleted: () => {
+ let prom = Promise.reject("Some error")
+ .then(
+ o => {console.log("Never reached");},
+ err => {
+ console.log("Rethrowing err");
+ throw err;
+ }
+ )
+ .catch(err => root.errorMessage = err)
+ }
+}
diff --git a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
index 41850d0263..b430434526 100644
--- a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
+++ b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
@@ -83,6 +83,7 @@ private slots:
void then_reject_non_callable();
void then_resolve_multiple_then();
void promiseChain();
+ void promiseHandlerThrows();
private:
void execute_test(QString testName);
@@ -285,6 +286,17 @@ void tst_qqmlpromise::promiseChain()
}
+void tst_qqmlpromise::promiseHandlerThrows()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("promisehandlerthrows.qml"));
+ QVERIFY(component.isReady());
+ QTest::ignoreMessage(QtDebugMsg, "Rethrowing err");
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root);
+ QTRY_VERIFY(root->property("errorMessage") == QLatin1String("Some error"));
+}
+
QTEST_MAIN(tst_qqmlpromise)
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/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 67da768f73..1a5927fa74 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -35,6 +35,9 @@
#include <private/qqmlboundsignal_p.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
+#if QT_CONFIG(regularexpression)
+#include <QtCore/qregularexpression.h>
+#endif
#include <QtCore/private/qobject_p.h>
#include "../../shared/util.h"
@@ -150,6 +153,8 @@ private slots:
void floatToStringPrecision();
void copy();
+
+ void bindingToAlias();
private:
QQmlEngine engine;
};
@@ -1989,11 +1994,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);
@@ -2015,9 +2018,13 @@ void tst_qqmlproperty::warnOnInvalidBinding()
expectedWarning = testUrl.toString() + QString::fromLatin1(":7:5: Unable to assign QQuickText to QQuickRectangle");
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
+#if QT_CONFIG(regularexpression)
// V8 error message for invalid binding to anchor
- expectedWarning = testUrl.toString() + QString::fromLatin1(":14:9: Unable to assign QQuickItem_QML_8 to QQuickAnchorLine");
- QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
+ const QRegularExpression warning(
+ "^" + testUrl.toString()
+ + ":14:9: Unable to assign QQuickItem_QML_\\d+ to QQuickAnchorLine$");
+ QTest::ignoreMessage(QtWarningMsg, warning);
+#endif
QQmlComponent component(&engine, testUrl);
QObject *obj = component.create();
@@ -2123,6 +2130,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());
+}
+
QTEST_MAIN(tst_qqmlproperty)
#include "tst_qqmlproperty.moc"
diff --git a/tests/auto/qml/qqmlpropertycache/data/SpecialObject1.qml b/tests/auto/qml/qqmlpropertycache/data/SpecialObject1.qml
new file mode 100644
index 0000000000..9559bc0b5f
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/SpecialObject1.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+ readonly property bool fakeProperty: false
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/SpecialObject2.qml b/tests/auto/qml/qqmlpropertycache/data/SpecialObject2.qml
new file mode 100644
index 0000000000..ed4ad04fef
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/SpecialObject2.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+ objectName: "special"
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/noDuckType.qml b/tests/auto/qml/qqmlpropertycache/data/noDuckType.qml
new file mode 100644
index 0000000000..5e1ea233b9
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/noDuckType.qml
@@ -0,0 +1,7 @@
+import QtQml 2.9
+
+QtObject {
+ property SpecialObject1 obj1: SpecialObject1 {}
+ property SpecialObject2 obj2: SpecialObject2 {}
+ property string result: (obj1 instanceof SpecialObject2) ? "bad" : "good"
+}
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index 9a1e4667dd..c9e92cd3c9 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -54,6 +54,7 @@ private slots:
void metaObjectSize_data();
void metaObjectSize();
void metaObjectChecksum();
+ void metaObjectsForRootElements();
private:
QQmlEngine engine;
@@ -543,4 +544,14 @@ void tst_qqmlpropertycache::metaObjectChecksum()
}
}
+void tst_qqmlpropertycache::metaObjectsForRootElements()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("noDuckType.qml"));
+ QVERIFY(c.isReady());
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("result").toString(), QString::fromLatin1("good"));
+}
+
QTEST_MAIN(tst_qqmlpropertycache)
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/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..15ef31464b 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -777,10 +777,6 @@ 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;
@@ -794,7 +790,11 @@ void tst_qqmlqt::dateTimeFormatting()
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);
@@ -853,7 +853,6 @@ void tst_qqmlqt::dateTimeFormattingVariants()
QFETCH(QStringList, expectedResults);
QQmlEngine eng;
- eng.rootContext()->setContextProperty("qvariant", variant);
QQmlComponent component(&eng, testFileUrl("formatting.qml"));
QStringList warnings;
@@ -867,7 +866,7 @@ void tst_qqmlqt::dateTimeFormattingVariants()
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);
@@ -1174,6 +1173,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 +1254,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/qqmltranslation/data/mylibrary.js b/tests/auto/qml/qqmltranslation/data/mylibrary.js
new file mode 100644
index 0000000000..5903db3b4b
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/mylibrary.js
@@ -0,0 +1,5 @@
+Qt.include("nested_js_translation.js")
+
+function translation_success() {
+ return qsTr("English in mylibrary");
+}
diff --git a/tests/auto/qml/qqmltranslation/data/nested_js_translation.js b/tests/auto/qml/qqmltranslation/data/nested_js_translation.js
new file mode 100644
index 0000000000..336cdedfea
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/nested_js_translation.js
@@ -0,0 +1,3 @@
+function translation_fail() {
+ return qsTr("English in translation")
+}
diff --git a/tests/auto/qml/qqmltranslation/data/preferjs.qml b/tests/auto/qml/qqmltranslation/data/preferjs.qml
new file mode 100644
index 0000000000..040fa12e4e
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/preferjs.qml
@@ -0,0 +1,8 @@
+import QtQml 2.12
+
+import "mylibrary.js" as Lib
+
+QtObject {
+ property string german1: Lib.translation_fail()
+ property string german2: Lib.translation_success()
+}
diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
index dcfe914af6..a75a00bd01 100644
--- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
+++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
@@ -46,6 +46,7 @@ private slots:
void translation();
void idTranslation();
void translationChange();
+ void preferJSContext();
};
void tst_qqmltranslation::translation_data()
@@ -175,6 +176,10 @@ class DummyTranslator : public QTranslator
Q_UNUSED(n);
if (!qstrcmp(sourceText, "translate me"))
return QString::fromUtf8("xxx");
+ if (!qstrcmp(sourceText, "English in mylibrary") && !qstrcmp(context, "mylibrary"))
+ return QString::fromUtf8("Deutsch in mylibrary");
+ if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "nested_js_translation"))
+ return QString::fromUtf8("Deutsch in Setzung");
return QString();
}
@@ -213,6 +218,24 @@ void tst_qqmltranslation::translationChange()
QCoreApplication::removeTranslator(&translator);
}
+void tst_qqmltranslation::preferJSContext()
+{
+ DummyTranslator translator;
+ QCoreApplication::installTranslator(&translator);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("preferjs.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("german1").toString(),
+ QStringLiteral("Deutsch in Setzung"));
+ QCOMPARE(object->property("german2").toString(),
+ QStringLiteral("Deutsch in mylibrary"));
+
+ QCoreApplication::removeTranslator(&translator);
+}
+
QTEST_MAIN(tst_qqmltranslation)
#include "tst_qqmltranslation.moc"
diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml
new file mode 100644
index 0000000000..28521e3af2
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.6
+
+Item {
+
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml
new file mode 100644
index 0000000000..b20a2def11
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.6
+import Com.Orga 1.0
+
+Rectangle {
+ color: Style.name
+ Text {text: "Hello world!"}
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir
new file mode 100644
index 0000000000..368cb65b35
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir
@@ -0,0 +1,2 @@
+module Com.Orga.Handlers
+Handler 1.0 Handler.qml
diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml
new file mode 100644
index 0000000000..7951f5e768
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQuick 2.6
+
+BaseStyle {
+ property color name: "black"
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir b/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir
new file mode 100644
index 0000000000..9c5560b323
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir
@@ -0,0 +1,2 @@
+singleton Style 1.0 Style.qml
+BaseStyle 1.0 BaseStyle.qml
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 63a43eebad..07f67c7843 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -60,6 +60,7 @@ private slots:
void implicitComponentModule();
void qrcRootPathUrl();
void implicitImport();
+ void compositeSingletonCycle();
private:
void checkSingleton(const QString & dataDirectory);
@@ -443,7 +444,7 @@ void tst_QQMLTypeLoader::redirect()
component.loadUrl(server.urlString("/Load.qml"), QQmlComponent::Asynchronous);
QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString()));
- QObject *object = component.create();
+ QScopedPointer<QObject> object {component.create()};
QTRY_COMPARE(object->property("xy").toInt(), 323232);
}
@@ -539,6 +540,23 @@ void tst_QQMLTypeLoader::implicitImport()
QVERIFY(!obj.isNull());
}
+void tst_QQMLTypeLoader::compositeSingletonCycle()
+{
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.serveDirectory(dataDirectory()));
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ engine.addImportPath(server.baseUrl().toString());
+ component.loadUrl(server.urlString("Com/Orga/Handlers/Handler.qml"), QQmlComponent::Asynchronous);
+ QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QScopedPointer<QObject> object {component.create()};
+ QVERIFY(object);
+ QCOMPARE(qvariant_cast<QColor>(object->property("color")), QColorConstants::Black);
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
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/color_read.qml b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
index 73d2b921a7..a2d303b507 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
@@ -12,4 +12,7 @@ MyTypeObject {
property real hsl_s: color.hslSaturation
property real hsl_l: color.hslLightness
property variant copy: color
+
+ property bool valid: color.valid
+ property bool invalid: invalidColor.valid
}
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index bcfe4028c6..798c96e188 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -69,6 +69,7 @@ class MyTypeObject : public QObject
Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix NOTIFY changed)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
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)
public:
@@ -168,6 +169,8 @@ public:
QColor color() const { return m_color; }
void setColor(const QColor &v) { m_color = v; emit changed(); }
+ QColor invalidColor() const { return QColor(); }
+
QVariant variant() const { return sizef(); }
void emitRunScript() { emit runScript(); }
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 8a602a0356..3e9047cc5a 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -97,6 +97,7 @@ private slots:
void enumerableProperties();
void enumProperties();
void scarceTypes();
+ void nonValueTypes();
private:
QQmlEngine engine;
@@ -934,6 +935,11 @@ void tst_qqmlvaluetypes::color()
QCOMPARE(qRound(object->property("hsl_s").toDouble() * 100), 74);
QCOMPARE(qRound(object->property("hsl_l").toDouble() * 100), 54);
+ QCOMPARE(object->property("valid").userType(), QMetaType::Bool);
+ QVERIFY(object->property("valid").toBool());
+ QCOMPARE(object->property("invalid").userType(), QMetaType::Bool);
+ QVERIFY(!object->property("invalid").toBool());
+
QColor comparison;
comparison.setRedF(0.2);
comparison.setGreenF(0.88);
@@ -1844,6 +1850,16 @@ void tst_qqmlvaluetypes::scarceTypes()
QCOMPARE(QByteArray(pixmapValue->vtable()->className), QByteArray("VariantObject"));
}
+#define CHECK_TYPE_IS_NOT_VALUETYPE(Type, typeId, cppType) \
+ QVERIFY(!QQmlValueTypeFactory::isValueType(QMetaType::Type));
+
+void tst_qqmlvaluetypes::nonValueTypes()
+{
+ CHECK_TYPE_IS_NOT_VALUETYPE(UnknownType, 0, void)
+ QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(CHECK_TYPE_IS_NOT_VALUETYPE);
+}
+
+#undef CHECK_TYPE_IS_NOT_VALUETYPE
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index b7600351b7..ae99e35467 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -75,6 +75,7 @@ private slots:
void introspectQrc();
void sortCaseSensitive_data();
void sortCaseSensitive();
+ void updateProperties();
private:
void checkNoErrors(const QQmlComponent& component);
QQmlEngine engine;
@@ -425,6 +426,47 @@ void tst_qquickfolderlistmodel::sortCaseSensitive()
QTRY_COMPARE(flm->data(flm->index(i),FileNameRole).toString(), expectedOrder.at(i));
}
+void tst_qquickfolderlistmodel::updateProperties()
+{
+ QQmlComponent component(&engine, testFileUrl("basic.qml"));
+ checkNoErrors(component);
+
+ QObject *folderListModel = component.create();
+ QVERIFY(folderListModel);
+
+ QVariant caseSensitive = folderListModel->property("caseSensitive");
+ QVERIFY(caseSensitive.isValid());
+ QCOMPARE(caseSensitive.toBool(), true);
+ folderListModel->setProperty("caseSensitive", false);
+ caseSensitive = folderListModel->property("caseSensitive");
+ QVERIFY(caseSensitive.isValid());
+ QCOMPARE(caseSensitive.toBool(), false);
+
+ QVariant showOnlyReadable = folderListModel->property("showOnlyReadable");
+ QVERIFY(showOnlyReadable.isValid());
+ QCOMPARE(showOnlyReadable.toBool(), false);
+ folderListModel->setProperty("showOnlyReadable", true);
+ showOnlyReadable = folderListModel->property("showOnlyReadable");
+ QVERIFY(showOnlyReadable.isValid());
+ QCOMPARE(showOnlyReadable.toBool(), true);
+
+ QVariant showDotAndDotDot = folderListModel->property("showDotAndDotDot");
+ QVERIFY(showDotAndDotDot.isValid());
+ QCOMPARE(showDotAndDotDot.toBool(), false);
+ folderListModel->setProperty("showDotAndDotDot", true);
+ showDotAndDotDot = folderListModel->property("showDotAndDotDot");
+ QVERIFY(showDotAndDotDot.isValid());
+ QCOMPARE(showDotAndDotDot.toBool(), true);
+
+ QVariant showHidden = folderListModel->property("showHidden");
+ QVERIFY(showHidden.isValid());
+ QCOMPARE(showHidden.toBool(), false);
+ folderListModel->setProperty("showHidden", true);
+ showHidden = folderListModel->property("showHidden");
+ QVERIFY(showHidden.isValid());
+ QCOMPARE(showHidden.toBool(), true);
+}
+
QTEST_MAIN(tst_qquickfolderlistmodel)
#include "tst_qquickfolderlistmodel.moc"
diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
index 308fba9049..157d0f2a62 100644
--- a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
+++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 basysKom GmbH.
** Contact: https://www.qt.io/licensing/
**
@@ -110,8 +111,8 @@ void tst_qv4identifiertable::sweepCenterEntryInBucket()
table.asPropertyKey(entry2);
table.asPropertyKey(entry3);
- QCOMPARE(table.size, 3);
- QCOMPARE(table.alloc, 5);
+ QCOMPARE(table.size, 3u);
+ QCOMPARE(table.alloc, 5u);
QCOMPARE(table.entriesByHash[0], entry1);
QCOMPARE(table.entriesByHash[1], entry2);
@@ -153,8 +154,8 @@ void tst_qv4identifiertable::sweepLastEntryInBucket()
table.asPropertyKey(entry2);
table.asPropertyKey(entry3);
- QCOMPARE(table.size, 3);
- QCOMPARE(table.alloc, 5);
+ QCOMPARE(table.size, 3u);
+ QCOMPARE(table.alloc, 5u);
QCOMPARE(table.entriesByHash[0], entry1);
QCOMPARE(table.entriesByHash[1], entry2);
@@ -193,8 +194,8 @@ void tst_qv4identifiertable::sweepFirstEntryInSameBucketWithDifferingHash()
table.asPropertyKey(entry1);
table.asPropertyKey(entry2);
- QCOMPARE(table.size, 2);
- QCOMPARE(table.alloc, 5);
+ QCOMPARE(table.size, 2u);
+ QCOMPARE(table.alloc, 5u);
QCOMPARE(table.entriesByHash[0], entry1);
QCOMPARE(table.entriesByHash[1], entry2);
@@ -231,8 +232,8 @@ void tst_qv4identifiertable::dontSweepAcrossBucketBoundaries()
table.asPropertyKey(entry1);
table.asPropertyKey(entry2);
- QCOMPARE(table.size, 2);
- QCOMPARE(table.alloc, 5);
+ QCOMPARE(table.size, 2u);
+ QCOMPARE(table.alloc, 5u);
QCOMPARE(table.entriesByHash[0], entry1);
QCOMPARE(table.entriesByHash[1], entry2);
@@ -279,8 +280,8 @@ void tst_qv4identifiertable::sweepAcrossBucketBoundariesIfFirstBucketFull()
table.asPropertyKey(entry3);
table.asPropertyKey(entry4);
- QCOMPARE(table.size, 4);
- QCOMPARE(table.alloc, 11);
+ QCOMPARE(table.size, 4u);
+ QCOMPARE(table.alloc, 11u);
QCOMPARE(table.entriesByHash[0], entry1);
QCOMPARE(table.entriesByHash[1], entry2);
@@ -336,8 +337,8 @@ void tst_qv4identifiertable::sweepBucketGap()
table.asPropertyKey(entry3);
table.asPropertyKey(entry4);
- QCOMPARE(table.size, 4);
- QCOMPARE(table.alloc, 11);
+ QCOMPARE(table.size, 4u);
+ QCOMPARE(table.alloc, 11u);
QCOMPARE(table.entriesByHash[0], entry1);
QCOMPARE(table.entriesByHash[1], entry2);
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index 66314f88a2..65c5ac9ef4 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);
@@ -282,6 +302,81 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(centroidChangedSpy.count(), shouldDrag ? 5 : 0);
}
+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
{
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
diff --git a/tests/auto/quick/qquickanimatedimage/data/currentframe.qml b/tests/auto/quick/qquickanimatedimage/data/currentframe.qml
new file mode 100644
index 0000000000..b679da2a99
--- /dev/null
+++ b/tests/auto/quick/qquickanimatedimage/data/currentframe.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+AnimatedImage {
+ property int currentFrameChangeCount: 0
+ property int frameChangeCount: 0
+ source: "stickman.gif"
+ onCurrentFrameChanged: if (currentFrame > 0) ++currentFrameChangeCount;
+ onFrameChanged: if (currentFrame > 0) ++frameChangeCount;
+ function scriptedSetCurrentFrame(frame) {
+ currentFrame = frame;
+ }
+}
+
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index 8026bafb9e..31c3fb9946 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <qtest.h>
#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/private/qquickrectangle_p.h>
@@ -40,6 +41,23 @@
Q_DECLARE_METATYPE(QQuickImageBase::Status)
+template <typename T> static T evaluate(QObject *scope, const QString &expression)
+{
+ QQmlExpression expr(qmlContext(scope), scope, expression);
+ QVariant result = expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+ return result.value<T>();
+}
+
+template <> void evaluate<void>(QObject *scope, const QString &expression)
+{
+ QQmlExpression expr(qmlContext(scope), scope, expression);
+ expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+}
+
class tst_qquickanimatedimage : public QQmlDataTest
{
Q_OBJECT
@@ -68,6 +86,7 @@ private slots:
void playingAndPausedChanges();
void noCaching();
void sourceChangesOnFrameChanged();
+ void currentFrame();
};
void tst_qquickanimatedimage::cleanup()
@@ -618,6 +637,33 @@ void tst_qquickanimatedimage::sourceChangesOnFrameChanged()
qDeleteAll(images);
}
+void tst_qquickanimatedimage::currentFrame()
+{
+ QQuickView window;
+ window.setSource(testFileUrl("currentframe.qml"));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject());
+ QVERIFY(anim);
+ QSignalSpy frameChangedSpy(anim, SIGNAL(frameChanged()));
+ QSignalSpy currentFrameChangedSpy(anim, SIGNAL(currentFrameChanged()));
+
+ anim->setCurrentFrame(1);
+ QCOMPARE(anim->currentFrame(), 1);
+ QCOMPARE(frameChangedSpy.count(), 1);
+ QCOMPARE(currentFrameChangedSpy.count(), 1);
+ QCOMPARE(anim->property("currentFrameChangeCount"), 1);
+ QCOMPARE(anim->property("frameChangeCount"), 1);
+
+ evaluate<void>(anim, "scriptedSetCurrentFrame(2)");
+ QCOMPARE(anim->currentFrame(), 2);
+ QCOMPARE(frameChangedSpy.count(), 2);
+ QCOMPARE(currentFrameChangedSpy.count(), 2);
+ QCOMPARE(anim->property("currentFrameChangeCount"), 2);
+ QCOMPARE(anim->property("frameChangeCount"), 2);
+}
+
QTEST_MAIN(tst_qquickanimatedimage)
#include "tst_qquickanimatedimage.moc"
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/qquickdrag/tst_qquickdrag.cpp b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
index 9d832066af..ee43e5e06a 100644
--- a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
+++ b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
@@ -598,7 +598,7 @@ void tst_QQuickDrag::move()
QCoreApplication::processEvents();
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&rightTarget));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&rightTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.moveEvents, 0);
QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
QCOMPARE(rightTarget.position.x(), qreal(5)); QCOMPARE(rightTarget.position.y(), qreal(15));
@@ -620,10 +620,10 @@ void tst_QQuickDrag::move()
QCoreApplication::processEvents();
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 1);
QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(40));
+ QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(5));
// Move out of all targets.
@@ -632,7 +632,7 @@ void tst_QQuickDrag::move()
QCoreApplication::processEvents();
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 1); QCOMPARE(leftTarget .moveEvents, 0);
QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
diff --git a/tests/auto/quick/qquickdroparea/data/nested1.qml b/tests/auto/quick/qquickdroparea/data/nested1.qml
new file mode 100644
index 0000000000..de6ac70d08
--- /dev/null
+++ b/tests/auto/quick/qquickdroparea/data/nested1.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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.0
+
+Item {
+ width: 200; height: 200
+ property int outerEnterEvents: 0
+ property int outerExitEvents: 0
+ property int innerEnterEvents: 0
+ property int innerExitEvents: 0
+
+ DropArea {
+ objectName: "outerDropArea"
+ x: 75; y: 75
+ width: 100; height: 100
+ Rectangle {
+ anchors.fill: parent
+ color: "green"
+ }
+ onEntered: ++outerEnterEvents
+ onExited: ++outerExitEvents
+
+ DropArea {
+ objectName: "innerDropArea"
+ width: 50; height: 50
+ Rectangle {
+ anchors.fill: parent
+ color: "blue"
+ }
+ onEntered: ++innerEnterEvents
+ onExited: ++innerExitEvents
+ }
+ }
+
+ Rectangle {
+ width: 20; height: 20
+ color: dragArea.pressed ? "red" : "brown"
+ Drag.active: dragArea.drag.active
+ MouseArea {
+ id: dragArea
+ objectName: "dragArea"
+ anchors.fill: parent
+ drag.target: parent
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickdroparea/data/nested2.qml b/tests/auto/quick/qquickdroparea/data/nested2.qml
new file mode 100644
index 0000000000..93630c3779
--- /dev/null
+++ b/tests/auto/quick/qquickdroparea/data/nested2.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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.0
+
+Item {
+ width: 200; height: 200
+ property int outerEnterEvents: 0
+ property int outerExitEvents: 0
+ property int innerEnterEvents: 0
+ property int innerExitEvents: 0
+
+ Rectangle {
+ x: 75; y: 75
+ width: 100; height: 100
+ color: "green"
+ DropArea {
+ objectName: "outerDropArea"
+ anchors.fill: parent
+ onEntered: ++outerEnterEvents
+ onExited: ++outerExitEvents
+ }
+
+ Rectangle {
+ width: 50; height: 50
+ color: "blue"
+ DropArea {
+ objectName: "innerDropArea"
+ anchors.fill: parent
+ onEntered: ++innerEnterEvents
+ onExited: ++innerExitEvents
+ }
+ }
+ }
+
+ Rectangle {
+ width: 20; height: 20
+ color: dragArea.pressed ? "red" : "brown"
+ Drag.active: dragArea.drag.active
+ MouseArea {
+ id: dragArea
+ objectName: "dragArea"
+ anchors.fill: parent
+ drag.target: parent
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickdroparea/qquickdroparea.pro b/tests/auto/quick/qquickdroparea/qquickdroparea.pro
index a34d5ad009..7a8fdef7b9 100644
--- a/tests/auto/quick/qquickdroparea/qquickdroparea.pro
+++ b/tests/auto/quick/qquickdroparea/qquickdroparea.pro
@@ -4,4 +4,11 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qquickdroparea.cpp
+OTHER_FILES += $$files(data/*.qml)
+
+include (../../shared/util.pri)
+include (../shared/util.pri)
+
+TESTDATA = data/*
+
QT += core-private gui-private qml-private quick-private network testlib
diff --git a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
index cf01cc927b..dcba4c872e 100644
--- a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
+++ b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
@@ -28,6 +28,7 @@
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
+#include <QtGui/qstylehints.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <QtQml/qqmlcontext.h>
@@ -36,6 +37,8 @@
#include <qpa/qplatformdrag.h>
#include <qpa/qwindowsysteminterface.h>
+#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
template <typename T> static T evaluate(QObject *scope, const QString &expression)
{
@@ -54,13 +57,10 @@ template <> void evaluate<void>(QObject *scope, const QString &expression)
qWarning() << expr.error().toString();
}
-class tst_QQuickDropArea: public QObject
+class tst_QQuickDropArea: public QQmlDataTest
{
Q_OBJECT
private slots:
- void initTestCase();
- void cleanupTestCase();
-
void containsDrag_internal();
void containsDrag_external();
void keys_internal();
@@ -74,21 +74,13 @@ private slots:
void competingDrags();
void simultaneousDrags();
void dropStuff();
+ void nestedDropAreas_data();
+ void nestedDropAreas();
private:
QQmlEngine engine;
};
-void tst_QQuickDropArea::initTestCase()
-{
-
-}
-
-void tst_QQuickDropArea::cleanupTestCase()
-{
-
-}
-
void tst_QQuickDropArea::containsDrag_internal()
{
QQuickWindow window;
@@ -1224,6 +1216,74 @@ void tst_QQuickDropArea::dropStuff()
QCOMPARE(evaluate<QByteArray>(dropArea, "array"), QByteArray("red"));
}
+void tst_QQuickDropArea::nestedDropAreas_data()
+{
+ QTest::addColumn<QString>("qmlFile");
+
+ QTest::newRow("dropRectDropRect") << "nested1.qml";
+ QTest::newRow("rectDropRectDrop") << "nested2.qml";
+}
+
+void tst_QQuickDropArea::nestedDropAreas()
+{
+ QFETCH(QString, qmlFile);
+
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QQuickView window;
+ QByteArray errorMessage;
+ QVERIFY2(QQuickTest::initView(window, testFileUrl(qmlFile.toLatin1().data()), true, &errorMessage), errorMessage.constData());
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject() != nullptr);
+
+ QQuickItem *dragArea = window.rootObject()->findChild<QQuickItem*>("dragArea");
+ QVERIFY(dragArea);
+ QQuickItem *outerDropArea = window.rootObject()->findChild<QQuickItem*>("outerDropArea");
+ QVERIFY(outerDropArea);
+ QQuickItem *innerDropArea = window.rootObject()->findChild<QQuickItem*>("innerDropArea");
+ QVERIFY(innerDropArea);
+
+ QPoint p = QPoint(10,10);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
+
+ // move the minimum distance to activate drag
+ p += QPoint(dragThreshold + 1, dragThreshold + 1);
+ QTest::mouseMove(&window, p);
+
+ // drag the red rectangle into the inner DropArea
+ p += QPoint(100, 100);
+ QTest::mouseMove(&window, p);
+ QCOMPARE(window.rootObject()->property("outerEnterEvents"), 0);
+ QCOMPARE(window.rootObject()->property("outerExitEvents"), 0);
+ QCOMPARE(window.rootObject()->property("innerEnterEvents"), 1);
+ QCOMPARE(window.rootObject()->property("innerExitEvents"), 0);
+
+ // drag the red rectangle into the outer DropArea
+ p += QPoint(0, 50);
+ QTest::mouseMove(&window, p);
+ QCOMPARE(window.rootObject()->property("outerEnterEvents"), 1);
+ QCOMPARE(window.rootObject()->property("outerExitEvents"), 0);
+ QCOMPARE(window.rootObject()->property("innerEnterEvents"), 1);
+ QCOMPARE(window.rootObject()->property("innerExitEvents"), 1);
+
+ // drag the red rectangle into the inner DropArea
+ p -= QPoint(0, 50);
+ QTest::mouseMove(&window, p);
+ QCOMPARE(window.rootObject()->property("outerEnterEvents"), 1);
+ QCOMPARE(window.rootObject()->property("outerExitEvents"), 1);
+ QCOMPARE(window.rootObject()->property("innerEnterEvents"), 2);
+ QCOMPARE(window.rootObject()->property("innerExitEvents"), 1);
+
+ // drag the red rectangle back out of both
+ p -= QPoint(100, 100);
+ QTest::mouseMove(&window, p);
+ QCOMPARE(window.rootObject()->property("outerEnterEvents"), 1);
+ QCOMPARE(window.rootObject()->property("outerExitEvents"), 1);
+ QCOMPARE(window.rootObject()->property("innerEnterEvents"), 2);
+ QCOMPARE(window.rootObject()->property("innerExitEvents"), 2);
+}
+
QTEST_MAIN(tst_QQuickDropArea)
#include "tst_qquickdroparea.moc"
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 c104eecbcd..5364530ca8 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -226,7 +226,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);
@@ -782,9 +782,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);
@@ -816,7 +815,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/qquicklayouts/data/tst_gridlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
index 6a1c0632ad..49838c4fd5 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
@@ -60,8 +60,8 @@ Item {
id: testCase
name: "Tests_GridLayout"
when: windowShown
- width: 200
- height: 200
+ width: parent.width
+ height: parent.height
Component {
id: layout_flow_Component
@@ -84,7 +84,7 @@ Item {
function test_flow()
{
- var layout = layout_flow_Component.createObject(container);
+ var layout = createTemporaryObject(layout_flow_Component, container);
tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
tryCompare(layout.children[1], "itemRect", [10, 0, 10, 10])
tryCompare(layout.children[2], "itemRect", [20, 0, 10, 10])
@@ -102,8 +102,6 @@ Item {
tryCompare(layout.children[4], "itemRect", [10, 0, 10, 10])
tryCompare(layout.children[5], "itemRect", [10, 10, 10, 10])
-
- layout.destroy()
}
Component {
@@ -178,7 +176,7 @@ Item {
}
function test_flowLeftToRight() {
- var layout = layout_flowLeftToRight_Component.createObject(container);
+ var layout = createTemporaryObject(layout_flowLeftToRight_Component, container);
compare(layout.implicitWidth, 80);
compare(layout.children[0].x, 0);
compare(layout.children[0].y, 0);
@@ -208,8 +206,6 @@ Item {
compare(layout.children[11].y, 60);
compare(layout.children[12].x, 40);
compare(layout.children[12].y, 80);
-
- layout.destroy();
}
@@ -259,7 +255,7 @@ Item {
function test_flowLeftToRightDefaultPositions() {
ignoreWarning("QGridLayoutEngine::addItem: Cell (1, 0) already taken");
- var layout = layout_flowLeftToRightDefaultPositions_Component.createObject(container);
+ var layout = createTemporaryObject(layout_flowLeftToRightDefaultPositions_Component, container);
compare(layout.implicitWidth, 40);
compare(layout.children[0].x, 0);
compare(layout.children[0].y, 0);
@@ -267,7 +263,6 @@ Item {
compare(layout.children[1].y, 20);
compare(layout.children[2].x, 20);
compare(layout.children[2].y, 20);
- layout.destroy();
}
@@ -342,7 +337,7 @@ Item {
}
function test_flowTopToBottom() {
- var layout = layout_flowTopToBottom_Component.createObject(container);
+ var layout = createTemporaryObject(layout_flowTopToBottom_Component, container);
compare(layout.children[0].x, 0);
compare(layout.children[0].y, 0);
compare(layout.children[1].x, 20);
@@ -371,8 +366,6 @@ Item {
compare(layout.children[11].y, 60);
compare(layout.children[12].x, 80);
compare(layout.children[12].y, 0);
-
- layout.destroy();
}
Component {
@@ -432,7 +425,7 @@ Item {
}
function test_spanAcrossEmptyRows() {
- var layout = layout_spanAcrossEmptyRows_Component.createObject(container);
+ var layout = createTemporaryObject(layout_spanAcrossEmptyRows_Component, container);
compare(layout.children[0].x, 0);
compare(layout.children[0].y, 0);
compare(layout.children[1].x, 20);
@@ -442,8 +435,6 @@ Item {
compare(layout.implicitWidth, 60);
compare(layout.Layout.maximumWidth, 120);
-
- layout.destroy();
}
Component {
@@ -463,14 +454,13 @@ Item {
}
function test_spanIsMoreThanColumns() {
- var layout = layout_spanIsMoreThanColumns_Component.createObject(container);
+ var layout = createTemporaryObject(layout_spanIsMoreThanColumns_Component, container);
// item was not added, therefore implicit width is 0
compare(layout.implicitWidth, 0);
- layout.destroy();
}
function test_sizeHints() {
- var layout = layout_spanAcrossEmptyRows_Component.createObject(container);
+ var layout = createTemporaryObject(layout_spanAcrossEmptyRows_Component, container);
compare(layout.visible, true)
var minWidth = layout.Layout.minimumWidth
@@ -489,8 +479,6 @@ Item {
compare(prefHeight, layout.implicitHeight)
compare(maxWidth, layout.Layout.maximumWidth)
compare(maxHeight, layout.Layout.maximumHeight)
-
- layout.destroy();
}
Component {
@@ -567,7 +555,7 @@ Item {
function test_alignment()
{
- var layout = layout_alignment_Component.createObject(container);
+ var layout = createTemporaryObject(layout_alignment_Component, container);
layout.width = 60;
layout.height = 100;
@@ -596,8 +584,6 @@ Item {
layout.children[4].Layout.alignment = Qt.AlignLeft
tryCompare(layout.children[4], "x", 0);
tryCompare(layout.children[4], "y", 60);
-
- layout.destroy();
}
@@ -648,7 +634,7 @@ Item {
function test_rightToLeft()
{
- var layout = layout_rightToLeft_Component.createObject(container);
+ var layout = createTemporaryObject(layout_rightToLeft_Component, container);
layout.width = 180;
layout.height = 50;
@@ -674,8 +660,6 @@ Item {
layout.LayoutMirroring.enabled = true
verifyIsRightToLeft(layout)
-
- layout.destroy();
}
Component {
@@ -698,7 +682,7 @@ Item {
function test_columnsChanged()
{
- var layout = layout_columnsOrRowsChanged_Component.createObject(container);
+ var layout = createTemporaryObject(layout_columnsOrRowsChanged_Component, container);
layout.width = 40;
layout.height = 20;
tryCompare(layout.children[0], "itemRect", [ 0, 5, 10, 10])
@@ -711,13 +695,11 @@ Item {
tryCompare(layout.children[1], "itemRect", [20, 0, 10, 10])
tryCompare(layout.children[2], "itemRect", [ 0, 10, 10, 10])
tryCompare(layout.children[3], "itemRect", [20, 10, 10, 10])
-
- layout.destroy()
}
function test_rowsChanged()
{
- var layout = layout_columnsOrRowsChanged_Component.createObject(container);
+ var layout = createTemporaryObject(layout_columnsOrRowsChanged_Component, container);
layout.flow = GridLayout.TopToBottom
layout.width = 20;
layout.height = 40;
@@ -731,8 +713,6 @@ Item {
tryCompare(layout.children[1], "itemRect", [ 0, 25, 10, 10])
tryCompare(layout.children[2], "itemRect", [10, 5, 10, 10])
tryCompare(layout.children[3], "itemRect", [10, 25, 10, 10])
-
- layout.destroy()
}
Component {
@@ -767,7 +747,7 @@ Item {
function test_columnOrRowChanged()
{
- var layout = layout_columnOrRowChanged_Component.createObject(container);
+ var layout = createTemporaryObject(layout_columnOrRowChanged_Component, container);
layout.width = layout.implicitWidth
layout.height = layout.implicitHeight
// c0-c1-c2
@@ -795,8 +775,6 @@ Item {
tryCompare(layout.children[0], "itemRect", [10, 10, 10, 10])
tryCompare(layout.children[1], "itemRect", [ 0, 0, 10, 10])
tryCompare(layout.children[2], "itemRect", [20, 0, 10, 10])
-
- layout.destroy()
}
Component {
@@ -819,7 +797,7 @@ Item {
}
function test_baselines()
{
- var layout = layout_baselines_Component.createObject(container);
+ var layout = createTemporaryObject(layout_baselines_Component, container);
tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
tryCompare(layout.children[1], "itemRect", [10, 0, 10, 10])
compare(layout.implicitWidth, 20)
@@ -832,8 +810,6 @@ Item {
tryCompare(layout.children[1], "itemRect", [10, 10, 10, 10])
compare(layout.implicitWidth, 20)
compare(layout.implicitHeight, 20)
-
- layout.destroy();
}
Component {
@@ -851,30 +827,42 @@ Item {
}
}
- function test_spacings()
+ function test_spacings_data()
+ {
+ let data = [
+ { spacing: Number.NaN },
+ { spacing: 0 },
+ { spacing: 10 },
+ { spacing: -5 },
+ { spacing: -19 }
+ ]
+ for (let i = 0; i < data.length; ++i) {
+ data[i].tag = data[i].spacing.toString()
+ }
+ return data
+ }
+
+ function test_spacings(data)
{
- var layout = layout_spacings_Component.createObject(container);
+ var layout = createTemporaryObject(layout_spacings_Component, container);
// breaks down below -19. This is acceptable, since it means that the implicit size of the layout is negative
var testSpacings = [Number.NaN, 0, 10, -5, -19]
layout.rowSpacing = 0
- for (var i = 0; i < testSpacings.length; ++i) {
- var sp = testSpacings[i]
- if (isNaN(sp)) {
- sp = 5 // Test defaults
- } else {
- layout.columnSpacing = sp
- }
- tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
- tryCompare(layout.children[1], "itemRect", [10 + sp, 0, 10, 10])
- compare(layout.implicitWidth, 20 + sp)
+ var spacing = data.spacing
+ if (isNaN(spacing)) {
+ spacing = 5 // Test defaults
+ } else {
+ layout.columnSpacing = spacing
}
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [10 + spacing, 0, 10, 10])
+ compare(layout.implicitWidth, 20 + spacing)
// do not crash
layout.columnSpacing = -100
waitForRendering(layout)
verify(isFinite(layout.implicitWidth))
- layout.destroy();
}
Component {
@@ -1026,11 +1014,10 @@ Item {
function test_invalidateWhileRearranging_QTBUG_44139()
{
- var layout = layout_invalidateWhileRearranging_Component.createObject(container)
+ var layout = createTemporaryObject(layout_invalidateWhileRearranging_Component, container)
waitForRendering(layout);
verify(layout.children[1].visible == false);
- layout.destroy()
}
}
}
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/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 08149a1786..fb5ae168e8 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -127,6 +127,7 @@ private slots:
void qAbstractItemModel_package_sections();
void qAbstractItemModel_sections();
void sectionsPositioning();
+ void sectionsDelegate_data();
void sectionsDelegate();
void sectionsDragOutsideBounds_data();
void sectionsDragOutsideBounds();
@@ -280,6 +281,8 @@ private slots:
void touchCancel();
void resizeAfterComponentComplete();
+ void delegateWithRequiredProperties();
+
private:
template <class T> void items(const QUrl &source);
template <class T> void changed(const QUrl &source);
@@ -389,7 +392,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");
}
@@ -1943,6 +1946,31 @@ void tst_QQuickListView::enforceRange()
QTRY_COMPARE(listview->currentIndex(), 6);
+ // Test for [QTBUG-77418] {
+ // explicit set current index
+ listview->setCurrentIndex(5);
+ QTRY_COMPARE(listview->contentY(), 0);
+
+ // then check if contentY changes if the highlight range is changed
+ listview->setPreferredHighlightBegin(80);
+ listview->setPreferredHighlightEnd(80);
+ QTRY_COMPARE(listview->contentY(), 20);
+
+ // verify that current index does not change with no highlight
+ listview->setHighlightRangeMode(QQuickListView::NoHighlightRange);
+ listview->setContentY(100);
+ QTRY_COMPARE(listview->currentIndex(), 5);
+
+ // explicit set current index, contentY should not change now
+ listview->setCurrentIndex(6);
+ QTRY_COMPARE(listview->contentY(), 100);
+ QTest::qWait(50); // This was needed in order to reproduce a failure for the following test
+
+ // verify that contentY changes if we turn on highlight again
+ listview->setHighlightRangeMode(QQuickListView::StrictlyEnforceRange);
+ QTRY_COMPARE(listview->contentY(), 40);
+ // } Test for [QTBUG-77418]
+
// change model
QaimModel model2;
for (int i = 0; i < 5; i++)
@@ -2158,8 +2186,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;
@@ -2169,7 +2206,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()));
@@ -9037,6 +9074,90 @@ 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);
+ }
+}
+
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 fbdd87905b..da923d4d41 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -681,6 +681,16 @@ void tst_QQuickLoader::initialPropertyValues_data()
<< QStringList()
<< (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(""));
}
void tst_QQuickLoader::initialPropertyValues()
diff --git a/tests/auto/quick/qquickmousearea/BLACKLIST b/tests/auto/quick/qquickmousearea/BLACKLIST
new file mode 100644
index 0000000000..f2cb00225b
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/BLACKLIST
@@ -0,0 +1,4 @@
+# QTBUG-78153
+[nestedStopAtBounds]
+opensuse-leap
+
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 5844720aa4..54a29dbc7f 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -307,7 +307,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));
@@ -326,7 +326,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());
}
@@ -1359,6 +1361,34 @@ void tst_QQuickMouseArea::hoverVisible()
QCOMPARE(enteredSpy.count(), 1);
QCOMPARE(QPointF(mouseTracker->mouseX(), mouseTracker->mouseY()), QPointF(11,33));
+
+ // QTBUG-77983
+ mouseTracker->setVisible(false);
+ mouseTracker->setEnabled(false);
+
+ QCOMPARE(mouseTracker->hovered(), false);
+ mouseTracker->setVisible(true);
+ // if the enabled property is false, the containsMouse property shouldn't become true
+ // when an invisible mousearea become visible
+ QCOMPARE(mouseTracker->hovered(), false);
+
+ mouseTracker->parentItem()->setEnabled(false);
+ mouseTracker->setVisible(false);
+ mouseTracker->setEnabled(true);
+
+ QCOMPARE(mouseTracker->hovered(), false);
+ mouseTracker->setVisible(true);
+ // if the parent item is not enabled, the containsMouse property will be false, even if
+ // the mousearea is enabled
+ QCOMPARE(mouseTracker->hovered(), false);
+
+ mouseTracker->parentItem()->setEnabled(true);
+ mouseTracker->setVisible(false);
+ mouseTracker->setEnabled(true);
+
+ QCOMPARE(mouseTracker->hovered(), false);
+ mouseTracker->setVisible(true);
+ QCOMPARE(mouseTracker->hovered(), true);
}
void tst_QQuickMouseArea::hoverAfterPress()
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index cd66fc4ede..e96b892b54 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -72,6 +72,7 @@ private slots:
void mouseGestureStarted_data();
void mouseGestureStarted();
void cancel();
+ void stationaryTouchWithChangingPressure();
private:
QQuickView *createAndShowView(const QString &file);
@@ -1305,6 +1306,42 @@ void tst_QQuickMultiPointTouchArea::cancel()
}
+void tst_QQuickMultiPointTouchArea::stationaryTouchWithChangingPressure() // QTBUG-77142
+{
+ QScopedPointer<QQuickView> window(createAndShowView("basic.qml"));
+ QVERIFY(window->rootObject() != nullptr);
+
+ QQuickTouchPoint *point1 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
+ QCOMPARE(point1->pressed(), false);
+
+ QPoint p1(20,100);
+ QTouchEvent::TouchPoint tp1(1);
+
+ tp1.setScreenPos(window->mapToGlobal(p1));
+ tp1.setState(Qt::TouchPointPressed);
+ tp1.setPressure(0.5);
+ qt_handleTouchEvent(window.data(), device, {tp1});
+ QQuickTouchUtils::flush(window.data());
+
+ QCOMPARE(point1->pressed(), true);
+ QCOMPARE(point1->pressure(), 0.5);
+
+ tp1.setState(Qt::TouchPointStationary);
+ tp1.setPressure(0.6);
+ qt_handleTouchEvent(window.data(), device, {tp1});
+ QQuickTouchUtils::flush(window.data());
+
+ QCOMPARE(point1->pressure(), 0.6);
+
+ tp1.setState(Qt::TouchPointReleased);
+ tp1.setPressure(0);
+ qt_handleTouchEvent(window.data(), device, {tp1});
+ QQuickTouchUtils::flush(window.data());
+
+ QCOMPARE(point1->pressed(), false);
+ QCOMPARE(point1->pressure(), 0);
+}
+
QTEST_MAIN(tst_QQuickMultiPointTouchArea)
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/data/nestedmousearea2.qml b/tests/auto/quick/qquickpathview/data/nestedmousearea2.qml
new file mode 100644
index 0000000000..ff11002552
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/nestedmousearea2.qml
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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.0
+
+PathView {
+ id: view
+ width: 400; height: 240
+ highlight: Rectangle { width: 80; height: 80; color: "lightsteelblue" }
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ model: ListModel {
+ id: appModel
+ ListElement { name: "Music" }
+ ListElement { name: "Movies" }
+ ListElement { name: "Camera" }
+ ListElement { name: "Calendar" }
+ ListElement { name: "Messaging" }
+ ListElement { name: "Todo List" }
+ ListElement { name: "Contacts" }
+ }
+ delegate: Rectangle {
+ width: 100; height: 100
+ scale: PathView.iconScale
+ border.color: "lightgrey"
+ color: "transparent"
+ Text {
+ anchors { horizontalCenter: parent.horizontalCenter }
+ text: name
+ smooth: true
+ color: ma.pressed ? "red" : "black"
+ }
+
+ MouseArea {
+ id: ma
+ anchors.fill: parent
+ onClicked: view.currentIndex = index
+ }
+ }
+ path: Path {
+ startX: 10
+ startY: 50
+ PathAttribute { name: "iconScale"; value: 0.5 }
+ PathQuad { x: 200; y: 150; controlX: 50; controlY: 200 }
+ PathAttribute { name: "iconScale"; value: 1.0 }
+ PathQuad { x: 390; y: 50; controlX: 350; controlY: 200 }
+ PathAttribute { name: "iconScale"; value: 0.5 }
+ }
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 20
+ text: view.currentIndex + " @ " + offset.toFixed(2)
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 8b963117ed..a8e847a5c7 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -120,6 +120,7 @@ private slots:
void undefinedPath();
void mouseDrag();
void nestedMouseAreaDrag();
+ void flickNClick();
void treeModel();
void changePreferredHighlight();
void missingPercent();
@@ -149,6 +150,8 @@ private slots:
void movementDirection();
void removePath();
void objectModelMove();
+ void requiredPropertiesInDelegate();
+ void requiredPropertiesInDelegatePreventUnrelated();
};
class TestObject : public QObject
@@ -1601,6 +1604,71 @@ void tst_QQuickPathView::nestedMouseAreaDrag()
QVERIFY(pathview->isMoving());
}
+void tst_QQuickPathView::flickNClick() // QTBUG-77173
+{
+ QScopedPointer<QQuickView> window(createView());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->setSource(testFileUrl("nestedmousearea2.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QCOMPARE(window.data(), qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
+ QVERIFY(pathview != nullptr);
+ QSignalSpy movingChangedSpy(pathview, SIGNAL(movingChanged()));
+ QSignalSpy draggingSpy(pathview, SIGNAL(draggingChanged()));
+ QSignalSpy dragStartedSpy(pathview, SIGNAL(dragStarted()));
+ QSignalSpy dragEndedSpy(pathview, SIGNAL(dragEnded()));
+ QSignalSpy currentIndexSpy(pathview, SIGNAL(currentIndexChanged()));
+ QSignalSpy moveStartedSpy(pathview, SIGNAL(movementStarted()));
+ QSignalSpy moveEndedSpy(pathview, SIGNAL(movementEnded()));
+ QSignalSpy flickingSpy(pathview, SIGNAL(flickingChanged()));
+ QSignalSpy flickStartedSpy(pathview, SIGNAL(flickStarted()));
+ QSignalSpy flickEndedSpy(pathview, SIGNAL(flickEnded()));
+
+ for (int duration = 100; duration > 0; duration -= 20) {
+ movingChangedSpy.clear();
+ draggingSpy.clear();
+ dragStartedSpy.clear();
+ dragEndedSpy.clear();
+ currentIndexSpy.clear();
+ moveStartedSpy.clear();
+ moveEndedSpy.clear();
+ flickingSpy.clear();
+ flickStartedSpy.clear();
+ flickEndedSpy.clear();
+ // Dragging the child mouse area should animate the PathView (MA has no drag target)
+ flick(window.data(), QPoint(200,200), QPoint(400,200), duration);
+ QVERIFY(pathview->isMoving());
+ QCOMPARE(movingChangedSpy.count(), 1);
+ QCOMPARE(draggingSpy.count(), 2);
+ QCOMPARE(dragStartedSpy.count(), 1);
+ QCOMPARE(dragEndedSpy.count(), 1);
+ QVERIFY(currentIndexSpy.count() > 0);
+ QCOMPARE(moveStartedSpy.count(), 1);
+ QCOMPARE(moveEndedSpy.count(), 0);
+ QCOMPARE(flickingSpy.count(), 1);
+ QCOMPARE(flickStartedSpy.count(), 1);
+ QCOMPARE(flickEndedSpy.count(), 0);
+
+ // Now while it's still moving, click it.
+ // The PathView should stop at a position such that offset is a whole number.
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(200, 200));
+ QTRY_VERIFY(!pathview->isMoving());
+ QCOMPARE(movingChangedSpy.count(), 2); // QTBUG-78926
+ QCOMPARE(draggingSpy.count(), 2);
+ QCOMPARE(dragStartedSpy.count(), 1);
+ QCOMPARE(dragEndedSpy.count(), 1);
+ QCOMPARE(moveStartedSpy.count(), 1);
+ QCOMPARE(moveEndedSpy.count(), 1);
+ QCOMPARE(flickingSpy.count(), 2);
+ QCOMPARE(flickStartedSpy.count(), 1);
+ QCOMPARE(flickEndedSpy.count(), 1);
+ QVERIFY(qFuzzyIsNull(pathview->offset() - int(pathview->offset())));
+ }
+}
+
void tst_QQuickPathView::treeModel()
{
QScopedPointer<QQuickView> window(createView());
@@ -2658,6 +2726,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/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/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/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..ccfef63902 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,7 @@ private slots:
void QTBUG54859_asynchronousMove();
void package();
void ownership();
+ void requiredProperties();
};
class TestObject : public QObject
@@ -143,6 +145,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 +167,7 @@ public:
void tst_QQuickRepeater::objectList()
{
+ QFETCH(QUrl, filename);
QQuickView *window = createView();
QObjectList data;
for (int i=0; i<100; i++)
@@ -165,7 +176,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");
@@ -1108,6 +1119,18 @@ 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);
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
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/data/tweakimplicitsize.qml b/tests/auto/quick/qquicktableview/data/tweakimplicitsize.qml
new file mode 100644
index 0000000000..ecc79a9368
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/tweakimplicitsize.qml
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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
+ property real delegateSize: 10
+ property int hideRow: -1
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ columnWidthProvider: function(column) {
+ return -1
+ }
+ rowHeightProvider: function(row) {
+ if (row === hideRow)
+ return 0
+ return -1
+ }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: row === 0 ? 10 : delegateSize
+ implicitHeight: column === 0 ? 10 : delegateSize
+ color: "lightgray"
+ border.width: 1
+
+ Text {
+ id: textItem
+ anchors.centerIn: parent
+ text: model.display
+ renderType: Text.NativeRendering
+ }
+ }
+ }
+
+}
+
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 19967efcd9..230dcc9446 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -119,6 +119,7 @@ private slots:
void checkRowHeightProviderNegativeReturnValue();
void checkRowHeightProviderNotCallable();
void checkForceLayoutFunction();
+ void checkForceLayoutEndUpDoingALayout();
void checkContentWidthAndHeight();
void checkPageFlicking();
void checkExplicitContentWidthAndHeight();
@@ -172,6 +173,7 @@ private slots:
void checkSyncView_differentSizedModels();
void checkSyncView_connect_late_data();
void checkSyncView_connect_late();
+ void delegateWithRequiredProperties();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -560,6 +562,32 @@ void tst_QQuickTableView::checkForceLayoutFunction()
QCOMPARE(fxItem->item->width(), newColumnWidth);
}
+void tst_QQuickTableView::checkForceLayoutEndUpDoingALayout()
+{
+ // QTBUG-77074
+ // Check that we change the implicit size of the delegate after
+ // the initial loading, and at the same time hide some rows or
+ // columns, and then do a forceLayout(), we end up with a
+ // complete relayout that respects the new implicit size.
+ LOAD_TABLEVIEW("tweakimplicitsize.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ const qreal newDelegateSize = 20;
+ view->rootObject()->setProperty("delegateSize", newDelegateSize);
+ // Hide a row, just to force the following relayout to
+ // do a complete reload (and not just a relayout)
+ view->rootObject()->setProperty("hideRow", 1);
+ tableView->forceLayout();
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->height(), newDelegateSize);
+}
+
void tst_QQuickTableView::checkContentWidthAndHeight()
{
// Check that contentWidth/Height reports the correct size of the
@@ -2592,6 +2620,50 @@ void tst_QQuickTableView::checkSyncView_connect_late()
}
+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());
+ }
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"
diff --git a/tests/auto/quick/qquicktext/data/transparentBackground.qml b/tests/auto/quick/qquicktext/data/transparentBackground.qml
new file mode 100644
index 0000000000..a10a1779bb
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/transparentBackground.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 200
+ height: 200
+ color: "white"
+ Text {
+ objectName: "text"
+ textFormat: Text.RichText
+ anchors.fill: parent
+ color: "black"
+ text: "<h1 style=\"background-color:rgba(255,255,255,0.00)\">foo</h1>"
+ verticalAlignment: Text.AlignTop
+ horizontalAlignment: Text.AlignLeft
+ }
+}
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 97107694bd..e62db81d27 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -164,6 +164,8 @@ private slots:
void verticallyAlignedImageInTable();
+ void transparentBackground();
+
private:
QStringList standard;
QStringList richText;
@@ -4429,6 +4431,26 @@ void tst_qquicktext::verticallyAlignedImageInTable()
// Don't crash
}
+void tst_qquicktext::transparentBackground()
+{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabToImage not functional on offscreen/minimimal platforms");
+
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("transparentBackground.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QImage img = window->grabWindow();
+ QCOMPARE(img.isNull(), false);
+
+ QColor color = img.pixelColor(0, 0);
+ 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 33a6b829bc..facd63027e 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -2106,30 +2106,31 @@ void tst_qquicktextedit::mouseSelection()
textEditObject->setFocus(focus);
textEditObject->setFocusOnPress(focusOnPress);
+ // Avoid that the last click from the previous test data and the first click in the
+ // current test data happens so close in time that they are interpreted as a double click.
+ static const int moreThanDoubleClickInterval = QGuiApplication::styleHints()->mouseDoubleClickInterval() + 1;
+
// press-and-drag-and-release from x1 to x2
QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
if (clicks == 2)
- QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1, moreThanDoubleClickInterval);
else if (clicks == 3)
- QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1, moreThanDoubleClickInterval);
+ // cancel the 500ms delta QTestLib adds in order to properly synthesize a triple click within the required interval
+ QTest::lastMouseTimestamp -= QTest::mouseDoubleClickInterval;
QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p1);
- if (clicks == 2) {
- // QTBUG-50022: Since qtbase commit beef975, QTestLib avoids generating
- // double click events by adding 500ms delta to release event timestamps.
- // Send a double click event by hand to ensure the correct sequence:
- // press, release, press, _dbl click_, move, release.
- QMouseEvent dblClickEvent(QEvent::MouseButtonDblClick, p1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
- QGuiApplication::sendEvent(textEditObject, &dblClickEvent);
- }
QTest::mouseMove(&window, p2);
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p2);
QTRY_COMPARE(textEditObject->selectedText(), selectedText);
// Clicking and shift to clicking between the same points should select the same text.
textEditObject->setCursorPosition(0);
- if (clicks > 1)
+ if (clicks > 1) {
QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ // cancel the 500ms delta QTestLib adds in order to properly synthesize a triple click within the required interval
+ QTest::lastMouseTimestamp -= QTest::mouseDoubleClickInterval;
+ }
if (clicks != 2)
QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
QTest::mouseClick(&window, Qt::LeftButton, Qt::ShiftModifier, p2);
diff --git a/tests/auto/quick/qquicktextinput/BLACKLIST b/tests/auto/quick/qquicktextinput/BLACKLIST
new file mode 100644
index 0000000000..ada7c57c75
--- /dev/null
+++ b/tests/auto/quick/qquicktextinput/BLACKLIST
@@ -0,0 +1,3 @@
+# QTBUG-78162
+[mouseSelectionMode]
+opensuse-leap
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index 32008f675a..fe56cad018 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -432,6 +432,7 @@ private slots:
void asynchronousCancel();
void invalidContext();
void externalManagedModel();
+ void delegateModelChangeDelegate();
private:
template <int N> void groups_verify(
@@ -4302,6 +4303,45 @@ void tst_qquickvisualdatamodel::externalManagedModel()
QTRY_VERIFY(!object->property("running").toBool());
}
+void tst_qquickvisualdatamodel::delegateModelChangeDelegate()
+{
+ // Verify that QTBUG-63477 is fixed.
+ // Changing the delegate would not update existing items.
+ QQmlEngine engine;
+ QScopedPointer<QQmlContext> context(new QQmlContext(engine.rootContext()));
+
+ QQmlComponent c(&engine);
+ c.setData("import QtQml.Models 2.2\nDelegateModel {}\n", QUrl());
+ QCOMPARE(c.status(), QQmlComponent::Ready);
+
+ QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create(context.data()));
+ QVERIFY(visualModel);
+ visualModel->setModel(QVariant(3));
+
+ QQmlComponent first(&engine);
+ first.setData("import QtQuick 2.0\nItem { objectName: \"old\" }\n", QUrl());
+ QCOMPARE(first.status(), QQmlComponent::Ready);
+
+ // Without delegate, claim to have an item count of 0
+ QCOMPARE(visualModel->count(), 0);
+
+ visualModel->setDelegate(&first);
+ // The first delegate has been set, verify we get it
+ QObject* old = visualModel->object(0, QQmlIncubator::Synchronous);
+ QVERIFY(old);
+ QCOMPARE(visualModel->object(0, QQmlIncubator::Synchronous)->objectName(), QStringLiteral("old"));
+ QCOMPARE(visualModel->count(), 3);
+
+ QQmlComponent second(&engine);
+ second.setData("import QtQuick 2.0\nItem { objectName: \"new\" }\n", QUrl());
+ QCOMPARE(second.status(), QQmlComponent::Ready);
+
+ visualModel->setDelegate(&second);
+ // After changing the delegate, expect the existing item to have the new delegate
+ QCOMPARE(visualModel->object(0, QQmlIncubator::Synchronous)->objectName(), QStringLiteral("new"));
+ QCOMPARE(visualModel->count(), 3);
+}
+
QTEST_MAIN(tst_qquickvisualdatamodel)
#include "tst_qquickvisualdatamodel.moc"
diff --git a/tests/auto/quick/qquickwindow/data/shortcut.qml b/tests/auto/quick/qquickwindow/data/shortcut.qml
new file mode 100644
index 0000000000..2632e27859
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/shortcut.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 QtQuick 2.9
+import QtQuick.Window 2.2
+
+Window {
+ id: root
+ visible: true
+ width: 200
+ height: 200
+ property bool received: false
+ Item {
+ focus: true
+ Shortcut {
+ sequence: "B"
+ onActivated: {
+ root.received = true
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index f08b9207d1..7faa621e86 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -482,6 +482,10 @@ private slots:
void testChildMouseEventFilter_data();
void cleanupGrabsOnRelease();
+#if QT_CONFIG(shortcut)
+ void testShortCut();
+#endif
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -3579,6 +3583,30 @@ void tst_qquickwindow::cleanupGrabsOnRelease()
QCOMPARE(parent->mouseUngrabEventCount, 1);
}
+#if QT_CONFIG(shortcut)
+void tst_qquickwindow::testShortCut()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("shortcut.qml"));
+
+ QObject *created = component.create();
+ QScopedPointer<QObject> cleanup(created);
+ QVERIFY(created);
+
+ QQuickWindow *window = qobject_cast<QQuickWindow *>(created);
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ EventFilter eventFilter;
+ window->activeFocusItem()->installEventFilter(&eventFilter);
+ //Send non-spontaneous key press event
+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_B, Qt::NoModifier);
+ QCoreApplication::sendEvent(window, &keyEvent);
+ QVERIFY(eventFilter.events.contains(int(QEvent::ShortcutOverride)));
+ QVERIFY(window->property("received").value<bool>());
+}
+#endif
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/manual/nodetypes_ng/nodetypes_ng.cpp b/tests/manual/nodetypes_ng/nodetypes_ng.cpp
index 829002b538..8fe0e0dc98 100644
--- a/tests/manual/nodetypes_ng/nodetypes_ng.cpp
+++ b/tests/manual/nodetypes_ng/nodetypes_ng.cpp
@@ -301,6 +301,13 @@ int main(int argc, char **argv)
fmt.setProfile(QSurfaceFormat::CoreProfile);
view.setFormat(fmt);
}
+ if (app.arguments().contains(QLatin1String("--transparent"))) {
+ qDebug("Requesting alpha channel for the window and using Qt::transparent as background");
+ QSurfaceFormat fmt = view.format();
+ fmt.setAlphaBufferSize(8);
+ view.setFormat(fmt);
+ view.setColor(Qt::transparent);
+ }
view.engine()->rootContext()->setContextProperty(QLatin1String("helper"), &helper);
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/tapWithModifiers.qml b/tests/manual/pointer/tapWithModifiers.qml
index 8ca1c1bd63..da3c0cb30a 100644
--- a/tests/manual/pointer/tapWithModifiers.qml
+++ b/tests/manual/pointer/tapWithModifiers.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 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.
@@ -40,6 +40,16 @@ Item {
onTapped: console.log("tapped with no modifiers")
}
TapHandler {
- onTapped: console.log("tapped with modifiers " + point.event.modifiers)
+ onTapped:
+ switch (point.modifiers) {
+ case Qt.ControlModifier | Qt.AltModifier:
+ console.log("CTRL+ALT");
+ break;
+ case Qt.ControlModifier | Qt.AltModifier | Qt.MetaModifier:
+ console.log("CTRL+META+ALT");
+ break;
+ default:
+ console.log("other modifiers", point.modifiers)
+ }
}
}
diff --git a/tests/manual/scenegraph_lancelot/hostinfo.sh b/tests/manual/scenegraph_lancelot/hostinfo.sh
deleted file mode 100644
index 6bad2ba467..0000000000
--- a/tests/manual/scenegraph_lancelot/hostinfo.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-#############################################################################
-##
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of the QtQml module of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE: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$
-##
-#############################################################################
-
-# printProperty(): prints a key-value pair from given key and cmd list.
-# If running cmd fails, or does not produce any stdout, nothing is printed.
-# Arguments: $1: key, $2: cmd, $3: optional, field specification as to cut(1) -f
-printProperty ()
-{
- key=$1
- val=`{ eval $2 ; } 2>/dev/null`
- [ -n "$3" ] && val=`echo $val | tr -s '[:blank:]' '\t' | cut -f$3`
- [ -n "$val" ] && echo $key: $val
-}
-
-# printEnvVar(): prints a key-value pair from given environment variable name.
-# key is printed as "Env_<varname>".
-# If the variable is undefined, nothing is printed.
-# Arguments: $1: varname
-
-printEnvVar ()
-{
- key=Env_$1
- val=`eval 'echo $'$1`
- [ -n "$val" ] && echo $key: $val
-}
-
-
-# printOnOff(): prints a key-value pair from given environment variable name.
-# If variable is defined, value is printed as "<key>-On"; otherwise "<key>-Off".
-# Arguments: $1: key $2: varname
-
-printOnOff ()
-{
- key=$1
- val=`eval 'echo $'$2`
- if [ -z "$val" ] ; then
- val=Off
- else
- val=On
- fi
- echo $key: $key-$val
-}
-
-# ------------
-
-printProperty Uname "uname -a"
-
-printProperty WlanMAC "ifconfig wlan0 | grep HWaddr" 5
-
-printEnvVar QMLSCENE_DEVICE
diff --git a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
index 6da0799bbc..23c678380c 100644
--- a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
+++ b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
@@ -36,6 +36,11 @@
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
+#ifdef Q_OS_WIN
+# include <fcntl.h>
+# include <io.h>
+#endif // Q_OS_WIN
+
// Timeout values:
// A valid screen grab requires the scene to not change
@@ -101,6 +106,10 @@ private slots:
#endif
if (ofile == "-") { // Write to stdout
QFile of;
+#ifdef Q_OS_WIN
+ // Make sure write to stdout doesn't do LF->CRLF
+ _setmode(_fileno(stdout), _O_BINARY);
+#endif // Q_OS_WIN
if (!of.open(1, QIODevice::WriteOnly) || !lastGrab.save(&of, "ppm")) {
qWarning() << "Error: failed to write grabbed image to stdout.";
QGuiApplication::exit(2);
diff --git a/tests/manual/scenegraph_lancelot/scenegraph/scenegraph.pro b/tests/manual/scenegraph_lancelot/scenegraph/scenegraph.pro
index 65819ab5bf..dd0ef268b1 100644
--- a/tests/manual/scenegraph_lancelot/scenegraph/scenegraph.pro
+++ b/tests/manual/scenegraph_lancelot/scenegraph/scenegraph.pro
@@ -9,3 +9,7 @@ SOURCES += tst_scenegraph.cpp
# Include Lancelot protocol code to communicate with baseline server.
# Assuming that we are in a normal Qt5 source code tree
include(../../../../../qtbase/tests/baselineserver/shared/qbaselinetest.pri)
+
+TEST_HELPER_INSTALLS += .././qmlscenegrabber
+
+TESTDATA += ../data
diff --git a/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp b/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp
index 3f28d90e7b..40b17ec2a2 100644
--- a/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp
+++ b/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp
@@ -68,6 +68,7 @@ private:
bool renderAndGrab(const QString& qmlFile, const QStringList& extraArgs, QImage *screenshot, QString *errMsg);
quint16 checksumFileOrDir(const QString &path);
+ QString testSuitePath;
int consecutiveErrors; // Not test failures (image mismatches), but system failures (so no image at all)
bool aborted; // This run given up because of too many system failures
};
@@ -81,6 +82,18 @@ tst_Scenegraph::tst_Scenegraph()
void tst_Scenegraph::initTestCase()
{
+ QString dataDir = QFINDTESTDATA("../data/.");
+ if (dataDir.isEmpty())
+ dataDir = QStringLiteral("data");
+ QFileInfo fi(dataDir);
+ if (!fi.exists() || !fi.isDir() || !fi.isReadable())
+ QSKIP("Test suite data directory missing or unreadable: " + fi.canonicalFilePath().toLatin1());
+ testSuitePath = fi.canonicalFilePath();
+
+ const char *backendVarName = "QT_QUICK_BACKEND";
+ const QString backend = qEnvironmentVariable(backendVarName, QString::fromLatin1("default"));
+ QBaselineTest::addClientProperty(QString::fromLatin1(backendVarName), backend);
+
QByteArray msg;
if (!QBaselineTest::connectToBaselineServer(&msg))
QSKIP(msg);
@@ -91,7 +104,7 @@ void tst_Scenegraph::cleanup()
{
// Allow subsystems time to settle
if (!aborted)
- QTest::qWait(200);
+ QTest::qWait(20);
}
void tst_Scenegraph::testNoTextRendering_data()
@@ -127,13 +140,6 @@ void tst_Scenegraph::setupTestSuite(const QByteArray& filter)
QTest::addColumn<QString>("qmlFile");
int numItems = 0;
- QString testSuiteDir = QLatin1String("data");
- QString testSuiteLocation = QCoreApplication::applicationDirPath();
- QString testSuitePath = testSuiteLocation + QDir::separator() + testSuiteDir;
- QFileInfo fi(testSuitePath);
- if (!fi.exists() || !fi.isDir() || !fi.isReadable())
- QSKIP("Test suite data directory missing or unreadable: " + testSuitePath.toLatin1());
-
QStringList ignoreItems;
QFile ignoreFile(testSuitePath + "/Ignore");
if (ignoreFile.open(QIODevice::ReadOnly)) {
@@ -233,7 +239,7 @@ quint16 tst_Scenegraph::checksumFileOrDir(const QString &path)
QFile f(path);
f.open(QIODevice::ReadOnly);
QByteArray contents = f.readAll();
- return qChecksum(contents.constData(), contents.size());
+ return qChecksum(contents.constData(), uint(contents.size()));
}
if (fi.isDir()) {
static const QStringList nameFilters = QStringList() << "*.qml" << "*.cpp" << "*.png" << "*.jpg";
diff --git a/tools/qml/conf.h b/tools/qml/conf.h
index 0c9d8613a0..e83d63cba5 100644
--- a/tools/qml/conf.h
+++ b/tools/qml/conf.h
@@ -30,6 +30,7 @@
#include <QtQml/QQmlContext>
#include <QtQml/QQmlListProperty>
+#include <QtQml/qqml.h>
#include <QObject>
#include <QUrl>
@@ -38,6 +39,7 @@ class PartialScene : public QObject
Q_OBJECT
Q_PROPERTY(QUrl container READ container WRITE setContainer NOTIFY containerChanged)
Q_PROPERTY(QString itemType READ itemType WRITE setItemType NOTIFY itemTypeChanged)
+ QML_ELEMENT
public:
PartialScene(QObject *parent = 0) : QObject(parent)
{}
@@ -72,6 +74,7 @@ class Config : public QObject
Q_OBJECT
Q_PROPERTY(QQmlListProperty<PartialScene> sceneCompleters READ sceneCompleters)
Q_CLASSINFO("DefaultProperty", "sceneCompleters")
+ QML_NAMED_ELEMENT(Configuration)
public:
Config (QObject* parent=0) : QObject(parent)
{}
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 9edc90e050..f7d7b98277 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -60,6 +60,7 @@
#include <qqml.h>
#include <qqmldebug.h>
+#include <private/qmemory_p.h>
#include <private/qtqmlglobal_p.h>
#if QT_CONFIG(qml_animation)
#include <private/qabstractanimation_p.h>
@@ -68,6 +69,7 @@
#include <cstdio>
#include <cstring>
#include <cstdlib>
+#include <memory>
#define FILE_OPEN_EVENT_WAIT_TIME 3000 // ms
@@ -398,23 +400,23 @@ static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory)
int main(int argc, char *argv[])
{
getAppFlags(argc, argv);
- QCoreApplication *app = nullptr;
+ std::unique_ptr<QCoreApplication> app;
switch (applicationType) {
#ifdef QT_GUI_LIB
case QmlApplicationTypeGui:
- app = new LoaderApplication(argc, argv);
+ app = qt_make_unique<LoaderApplication>(argc, argv);
break;
#ifdef QT_WIDGETS_LIB
case QmlApplicationTypeWidget:
- app = new QApplication(argc, argv);
- static_cast<QApplication *>(app)->setWindowIcon(QIcon(iconResourcePath));
+ app = qt_make_unique<QApplication>(argc, argv);
+ static_cast<QApplication *>(app.get())->setWindowIcon(QIcon(iconResourcePath));
break;
#endif // QT_WIDGETS_LIB
#endif // QT_GUI_LIB
case QmlApplicationTypeCore:
Q_FALLTHROUGH();
default: // QmlApplicationTypeUnknown: not allowed, but we'll exit after checking apptypeOption below
- app = new QCoreApplication(argc, argv);
+ app = qt_make_unique<QCoreApplication>(argc, argv);
break;
}
@@ -423,8 +425,7 @@ int main(int argc, char *argv[])
app->setOrganizationDomain("qt-project.org");
QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
- qmlRegisterType<Config>("QmlRuntime.Config", 1, 0, "Configuration");
- qmlRegisterType<PartialScene>("QmlRuntime.Config", 1, 0, "PartialScene");
+ qmlRegisterTypesAndRevisions<Config, PartialScene>("QmlRuntime.Config", 1);
QQmlApplicationEngine e;
QStringList files;
QString confFile;
@@ -598,7 +599,7 @@ int main(int argc, char *argv[])
if (files.count() <= 0) {
#if defined(Q_OS_DARWIN)
if (applicationType == QmlApplicationTypeGui)
- exitTimerId = static_cast<LoaderApplication *>(app)->startTimer(FILE_OPEN_EVENT_WAIT_TIME);
+ exitTimerId = static_cast<LoaderApplication *>(app.get())->startTimer(FILE_OPEN_EVENT_WAIT_TIME);
else
#endif
noFilesGiven();
diff --git a/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in b/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in
index 75fbb0fcf3..be2113b258 100644
--- a/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in
+++ b/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in
@@ -50,13 +50,9 @@ but not all the files it references.
get_filename_component(input_resource ${_resource} ABSOLUTE)
- execute_process(COMMAND ${compiler_path} -filter-resource-file ${input_resource} -o ${new_resource_file} OUTPUT_VARIABLE remaining_files)
- if(remaining_files)
- list(APPEND filtered_rcc_files ${new_resource_file})
- list(APPEND loader_flags \"--resource-file-mapping=${_resource}=${new_resource_file}\")
- else()
- list(APPEND loader_flags \"--resource-file-mapping=${_resource}\")
- endif()
+ execute_process(COMMAND ${compiler_path} --filter-resource-file ${input_resource} -o ${new_resource_file} OUTPUT_VARIABLE remaining_files)
+ list(APPEND filtered_rcc_files ${new_resource_file})
+ list(APPEND loader_flags \"--resource-file-mapping=${_resource}=${new_resource_file}\")
set(rcc_file_with_compilation_units)
diff --git a/tools/qmlcachegen/generateloader.cpp b/tools/qmlcachegen/generateloader.cpp
index 1c8a5a016a..71286137eb 100644
--- a/tools/qmlcachegen/generateloader.cpp
+++ b/tools/qmlcachegen/generateloader.cpp
@@ -100,228 +100,6 @@ QString symbolNamespaceForPath(const QString &relativePath)
return mangledIdentifier(symbol);
}
-struct VirtualDirectoryEntry
-{
- QString name;
- QVector<VirtualDirectoryEntry*> dirEntries;
- int firstChildIndex = -1; // node index inside generated data
- bool isDirectory = true;
-
- VirtualDirectoryEntry()
- {}
-
- ~VirtualDirectoryEntry()
- {
- qDeleteAll(dirEntries);
- }
-
- VirtualDirectoryEntry *append(const QString &name)
- {
- for (QVector<VirtualDirectoryEntry*>::Iterator it = dirEntries.begin(), end = dirEntries.end();
- it != end; ++it) {
- if ((*it)->name == name)
- return *it;
- }
-
- VirtualDirectoryEntry *subEntry = new VirtualDirectoryEntry;
- subEntry->name = name;
- dirEntries.append(subEntry);
- return subEntry;
- }
-
- void appendEmptyFile(const QString &name)
- {
- VirtualDirectoryEntry *subEntry = new VirtualDirectoryEntry;
- subEntry->name = name;
- subEntry->isDirectory = false;
- dirEntries.append(subEntry);
- }
-
- bool isEmpty() const { return dirEntries.isEmpty(); }
-};
-
-struct DataStream
-{
- DataStream(QVector<unsigned char > *data = nullptr)
- : data(data)
- {}
-
- qint64 currentOffset() const { return data->size(); }
-
- DataStream &operator<<(quint16 value)
- {
- unsigned char d[2];
- qToBigEndian(value, d);
- data->append(d[0]);
- data->append(d[1]);
- return *this;
- }
- DataStream &operator<<(quint32 value)
- {
- unsigned char d[4];
- qToBigEndian(value, d);
- data->append(d[0]);
- data->append(d[1]);
- data->append(d[2]);
- data->append(d[3]);
- return *this;
- }
-private:
- QVector<unsigned char> *data;
-};
-
-static bool resource_sort_order(const VirtualDirectoryEntry *lhs, const VirtualDirectoryEntry *rhs)
-{
- return qt_hash(lhs->name) < qt_hash(rhs->name);
-}
-
-struct ResourceTree
-{
- ResourceTree()
- {}
-
- void serialize(VirtualDirectoryEntry &root, QVector<unsigned char> *treeData, QVector<unsigned char> *stringData)
- {
- treeStream = DataStream(treeData);
- stringStream = DataStream(stringData);
-
- QStack<VirtualDirectoryEntry *> directories;
-
- {
- directories.push(&root);
- while (!directories.isEmpty()) {
- VirtualDirectoryEntry *entry = directories.pop();
- registerString(entry->name);
- if (entry->isDirectory)
- directories << entry->dirEntries;
- }
- }
-
- {
- quint32 currentDirectoryIndex = 1;
- directories.push(&root);
- while (!directories.isEmpty()) {
- VirtualDirectoryEntry *entry = directories.pop();
- entry->firstChildIndex = currentDirectoryIndex;
- currentDirectoryIndex += entry->dirEntries.count();
- std::sort(entry->dirEntries.begin(), entry->dirEntries.end(), resource_sort_order);
-
- for (QVector<VirtualDirectoryEntry*>::ConstIterator child = entry->dirEntries.constBegin(), end = entry->dirEntries.constEnd();
- child != end; ++child) {
- if ((*child)->isDirectory)
- directories << *child;
- }
- }
- }
-
- {
- writeTreeEntry(&root);
- directories.push(&root);
- while (!directories.isEmpty()) {
- VirtualDirectoryEntry *entry = directories.pop();
-
- for (QVector<VirtualDirectoryEntry*>::ConstIterator child = entry->dirEntries.constBegin(), end = entry->dirEntries.constEnd();
- child != end; ++child) {
- writeTreeEntry(*child);
- if ((*child)->isDirectory)
- directories << (*child);
- }
- }
- }
- }
-
-private:
- DataStream treeStream;
- DataStream stringStream;
- QHash<QString, qint64> stringOffsets;
-
- void registerString(const QString &name)
- {
- if (stringOffsets.contains(name))
- return;
- const qint64 offset = stringStream.currentOffset();
- stringOffsets.insert(name, offset);
-
- stringStream << quint16(name.length())
- << quint32(qt_hash(name));
- for (int i = 0; i < name.length(); ++i)
- stringStream << quint16(name.at(i).unicode());
- }
-
- void writeTreeEntry(VirtualDirectoryEntry *entry)
- {
- treeStream << quint32(stringOffsets.value(entry->name))
- << quint16(entry->isDirectory ? 0x2 : 0x0); // Flags: File or Directory
-
- if (entry->isDirectory) {
- treeStream << quint32(entry->dirEntries.count())
- << quint32(entry->firstChildIndex);
- } else {
- treeStream << quint16(QLocale::AnyCountry) << quint16(QLocale::C)
- << quint32(0x0);
- }
- }
-};
-
-static QByteArray generateResourceDirectoryTree(QTextStream &code, const QStringList &qrcFiles,
- const QStringList &sortedRetainedFiles)
-{
- QByteArray call;
- if (qrcFiles.isEmpty())
- return call;
-
- VirtualDirectoryEntry resourceDirs;
- resourceDirs.name = QStringLiteral("/");
-
- for (const QString &entry : qrcFiles) {
- const QStringList segments = entry.split(QLatin1Char('/'), QString::SkipEmptyParts);
-
- VirtualDirectoryEntry *dirEntry = &resourceDirs;
-
- for (int i = 0; i < segments.count() - 1; ++i)
- dirEntry = dirEntry->append(segments.at(i));
- if (!std::binary_search(sortedRetainedFiles.begin(), sortedRetainedFiles.end(), entry))
- dirEntry->appendEmptyFile(segments.last());
- }
-
- if (resourceDirs.isEmpty())
- return call;
-
- QVector<unsigned char> names;
- QVector<unsigned char> tree;
- ResourceTree().serialize(resourceDirs, &tree, &names);
-
- code << "static const unsigned char qt_resource_tree[] = {\n";
- for (int i = 0; i < tree.count(); ++i) {
- code << uint(tree.at(i));
- if (i < tree.count() - 1)
- code << ',';
- if (i % 16 == 0)
- code << '\n';
- }
- code << "};\n";
-
- code << "static const unsigned char qt_resource_names[] = {\n";
- for (int i = 0; i < names.count(); ++i) {
- code << uint(names.at(i));
- if (i < names.count() - 1)
- code << ',';
- if (i % 16 == 0)
- code << '\n';
- }
- code << "};\n";
-
- code << "static const unsigned char qt_resource_empty_payout[] = { 0, 0, 0, 0, 0 };\n";
-
- code << "QT_BEGIN_NAMESPACE\n";
- code << "extern Q_CORE_EXPORT bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);\n";
- code << "QT_END_NAMESPACE\n";
-
- call = "QT_PREPEND_NAMESPACE(qRegisterResourceData)(/*version*/0x01, qt_resource_tree, qt_resource_names, qt_resource_empty_payout);\n";
-
- return call;
-}
-
static QString qtResourceNameForFile(const QString &fileName)
{
QFileInfo fi(fileName);
@@ -332,9 +110,8 @@ static QString qtResourceNameForFile(const QString &fileName)
return name;
}
-bool generateLoader(const QStringList &compiledFiles, const QStringList &sortedRetainedFiles,
- const QString &outputFileName, const QStringList &resourceFileMappings,
- QString *errorString)
+bool generateLoader(const QStringList &compiledFiles, const QString &outputFileName,
+ const QStringList &resourceFileMappings, QString *errorString)
{
QByteArray generatedLoaderCode;
@@ -345,9 +122,6 @@ bool generateLoader(const QStringList &compiledFiles, const QStringList &sortedR
stream << "#include <QtCore/qurl.h>\n";
stream << "\n";
- QByteArray resourceRegisterCall = generateResourceDirectoryTree(stream, compiledFiles,
- sortedRetainedFiles);
-
stream << "namespace QmlCacheGeneratedCode {\n";
for (int i = 0; i < compiledFiles.count(); ++i) {
const QString compiledFile = compiledFiles.at(i);
@@ -385,9 +159,6 @@ bool generateLoader(const QStringList &compiledFiles, const QStringList &sortedR
stream << " registration.lookupCachedQmlUnit = &lookupCachedUnit;\n";
stream << " QQmlPrivate::qmlregister(QQmlPrivate::QmlUnitCacheHookRegistration, &registration);\n";
- if (!resourceRegisterCall.isEmpty())
- stream << resourceRegisterCall;
-
stream << "}\n\n";
stream << "Registry::~Registry() {\n";
stream << " QQmlPrivate::qmlunregister(QQmlPrivate::QmlUnitCacheHookRegistration, quintptr(&lookupCachedUnit));\n";
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index 6e96b88c0c..d1b28c41f5 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -48,9 +48,8 @@
using namespace QQmlJS;
int filterResourceFile(const QString &input, const QString &output);
-bool generateLoader(const QStringList &compiledFiles, const QStringList &retainedFiles,
- const QString &output, const QStringList &resourceFileMappings,
- QString *errorString);
+bool generateLoader(const QStringList &compiledFiles, const QString &output,
+ const QStringList &resourceFileMappings, QString *errorString);
QString symbolNamespaceForPath(const QString &relativePath);
QSet<QString> illegalNames;
@@ -455,8 +454,6 @@ int main(int argc, char **argv)
parser.addOption(resourceFileMappingOption);
QCommandLineOption resourceOption(QStringLiteral("resource"), QCoreApplication::translate("main", "Qt resource file that might later contain one of the compiled files"), QCoreApplication::translate("main", "resource-file-name"));
parser.addOption(resourceOption);
- QCommandLineOption retainOption(QStringLiteral("retain"), QCoreApplication::translate("main", "Qt resource file the contents of which should not be replaced by empty stubs"), QCoreApplication::translate("main", "resource-file-name"));
- parser.addOption(retainOption);
QCommandLineOption resourcePathOption(QStringLiteral("resource-path"), QCoreApplication::translate("main", "Qt resource file path corresponding to the file being compiled"), QCoreApplication::translate("main", "resource-path"));
parser.addOption(resourcePathOption);
QCommandLineOption resourceNameOption(QStringLiteral("resource-name"),
@@ -517,12 +514,9 @@ int main(int argc, char **argv)
if (target == GenerateLoader) {
ResourceFileMapper mapper(sources);
- ResourceFileMapper retain(parser.values(retainOption));
Error error;
- QStringList retainedFiles = retain.qmlCompilerFiles();
- std::sort(retainedFiles.begin(), retainedFiles.end());
- if (!generateLoader(mapper.qmlCompilerFiles(), retainedFiles, outputFileName,
+ if (!generateLoader(mapper.qmlCompilerFiles(), outputFileName,
parser.values(resourceFileMappingOption), &error.message)) {
error.augment(QLatin1String("Error generating loader stub: ")).print();
return EXIT_FAILURE;
@@ -531,10 +525,8 @@ int main(int argc, char **argv)
}
if (target == GenerateLoaderStandAlone) {
- QStringList retainedFiles = parser.values(retainOption);
- retainedFiles.sort();
Error error;
- if (!generateLoader(sources, retainedFiles, outputFileName,
+ if (!generateLoader(sources, outputFileName,
parser.values(resourceNameOption), &error.message)) {
error.augment(QLatin1String("Error generating loader stub: ")).print();
return EXIT_FAILURE;
diff --git a/tools/qmlcachegen/qtquickcompiler.prf b/tools/qmlcachegen/qtquickcompiler.prf
index 2f98aadefe..a31a7f5714 100644
--- a/tools/qmlcachegen/qtquickcompiler.prf
+++ b/tools/qmlcachegen/qtquickcompiler.prf
@@ -1,5 +1,15 @@
if(qtc_run|lupdate_run): return()
+!contains(QT, qml) {
+ qt_modules = \
+ $$replace(QT, -private$, _private) \
+ $$replace(QT_PRIVATE, -private$, _private)
+ qt_modules = $$resolve_depends(qt_modules, "QT.", ".depends" ".run_depends")
+ !contains(qt_modules, qml): \
+ return()
+ unset(qt_modules)
+}
+
qtPrepareTool(QML_CACHEGEN, qmlcachegen, _FILTER)
qtPrepareTool(QMAKE_RCC, rcc, _DEP)
@@ -16,20 +26,6 @@ defineReplace(qmlCacheResourceFileOutputName) {
return($${name})
}
-defineTest(qtQuickRetainSources) {
- for(retainedRes, QTQUICK_COMPILER_RETAINED_RESOURCES) {
- equals(1, $$retainedRes): return(true)
- }
- return(false)
-}
-
-defineTest(qtQuickSkippedResourceFile) {
- for(skippedRes, QTQUICK_COMPILER_SKIPPED_RESOURCES) {
- equals(1, $$skippedRes): return(true)
- }
- return(false)
-}
-
# Flatten RESOURCES that may contain individual files or objects
load(resources)
@@ -37,29 +33,14 @@ NEWRESOURCES =
QMLCACHE_RESOURCE_FILES =
for(res, RESOURCES) {
- qtQuickSkippedResourceFile($$res) {
- NEWRESOURCES += $$res
- next()
- }
-
absRes = $$absolute_path($$res, $$_PRO_FILE_PWD_)
rccContents = $$system($$QMAKE_RCC_DEP -list $$system_quote($$absRes),lines)
contains(rccContents,.*\\.js$)|contains(rccContents,.*\\.qml$)|contains(rccContents,.*\\.mjs$) {
new_resource = $$qmlCacheResourceFileOutputName($$res)
mkpath($$dirname(new_resource))
- qtQuickRetainSources($$res) {
- NEWRESOURCES += $$res
- QMLCACHE_LOADER_FLAGS += --retain=$$shell_quote($$absRes)
- } else {
- remaining_files = $$system($$QML_CACHEGEN_FILTER -filter-resource-file \
- -o $$system_quote($$new_resource) $$system_quote($$absRes),lines)
- !isEmpty(remaining_files) {
- NEWRESOURCES += $$new_resource
- QMLCACHE_LOADER_FLAGS += --resource-file-mapping=$$shell_quote($$absRes=$$new_resource)
- } else {
- QMLCACHE_LOADER_FLAGS += --resource-file-mapping=$$shell_quote($$absRes)
- }
- }
+ dummy = $$system($$QML_CACHEGEN_FILTER --filter-resource-file -o $$system_quote($$new_resource) $$system_quote($$absRes))
+ NEWRESOURCES += $$new_resource
+ QMLCACHE_LOADER_FLAGS += --resource-file-mapping=$$shell_quote($$absRes=$$new_resource)
QMLCACHE_RESOURCE_FILES += $$absRes
diff --git a/tools/qmlcachegen/resourcefilter.cpp b/tools/qmlcachegen/resourcefilter.cpp
index 3ad6e9ca0d..261102dcbe 100644
--- a/tools/qmlcachegen/resourcefilter.cpp
+++ b/tools/qmlcachegen/resourcefilter.cpp
@@ -57,8 +57,6 @@ int filterResourceFile(const QString &input, const QString &output)
QXmlStreamWriter writer(&outputString);
writer.setAutoFormatting(true);
- QStringList remainingFiles;
-
QXmlStreamReader reader(&file);
while (!reader.atEnd()) {
switch (reader.readNext()) {
@@ -139,47 +137,36 @@ int filterResourceFile(const QString &input, const QString &output)
if (currentFileName.isEmpty())
continue;
- if (!currentFileName.endsWith(QStringLiteral(".qml"))
- && !currentFileName.endsWith(QStringLiteral(".js"))
- && !currentFileName.endsWith(QStringLiteral(".mjs"))) {
- writer.writeStartElement(QStringLiteral("file"));
-
- if (!fileAttributes.hasAttribute(QStringLiteral("alias")))
- fileAttributes.append(QStringLiteral("alias"), currentFileName);
+ writer.writeStartElement(QStringLiteral("file"));
- currentFileName = inputDirectory.absoluteFilePath(currentFileName);
- currentFileName = outputDirectory.relativeFilePath(currentFileName);
+ if (!fileAttributes.hasAttribute(QStringLiteral("alias")))
+ fileAttributes.append(QStringLiteral("alias"), currentFileName);
- remainingFiles << currentFileName;
+ currentFileName = inputDirectory.absoluteFilePath(currentFileName);
+ currentFileName = outputDirectory.relativeFilePath(currentFileName);
- writer.writeAttributes(fileAttributes);
- writer.writeCharacters(currentFileName);
- writer.writeEndElement();
- }
+ writer.writeAttributes(fileAttributes);
+ writer.writeCharacters(currentFileName);
+ writer.writeEndElement();
continue;
default: break;
}
}
- if (!remainingFiles.isEmpty()) {
- QFile outputFile(output);
- if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- fprintf(stderr, "Cannot open %s for writing.\n", qPrintable(output));
- return EXIT_FAILURE;
- }
- const QByteArray outputStringUtf8 = outputString.toUtf8();
- if (outputFile.write(outputStringUtf8) != outputStringUtf8.size())
- return EXIT_FAILURE;
+ QFile outputFile(output);
+ if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ fprintf(stderr, "Cannot open %s for writing.\n", qPrintable(output));
+ return EXIT_FAILURE;
+ }
+ const QByteArray outputStringUtf8 = outputString.toUtf8();
+ if (outputFile.write(outputStringUtf8) != outputStringUtf8.size())
+ return EXIT_FAILURE;
- outputFile.close();
- if (outputFile.error() != QFileDevice::NoError)
- return EXIT_FAILURE;
+ outputFile.close();
+ if (outputFile.error() != QFileDevice::NoError)
+ return EXIT_FAILURE;
- // The build system expects this output if we wrote a qrc file and no output
- // if no files remain.
- fprintf(stdout, "New resource file written with %d files.\n", remainingFiles.count());
- }
return EXIT_SUCCESS;
}
diff --git a/tools/qmllint/fakemetaobject.cpp b/tools/qmllint/fakemetaobject.cpp
index 514bb2fe42..8319ae6713 100644
--- a/tools/qmllint/fakemetaobject.cpp
+++ b/tools/qmllint/fakemetaobject.cpp
@@ -46,8 +46,8 @@ QString FakeMetaEnum::name() const
void FakeMetaEnum::setName(const QString &name)
{ m_name = name; }
-void FakeMetaEnum::addKey(const QString &key, int value)
-{ m_keys.append(key); m_values.append(value); }
+void FakeMetaEnum::addKey(const QString &key)
+{ m_keys.append(key); }
QString FakeMetaEnum::key(int index) const
{ return m_keys.at(index); }
@@ -73,10 +73,6 @@ void FakeMetaEnum::addToHash(QCryptographicHash &hash) const
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
}
- len = m_values.size();
- hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
- foreach (int value, m_values)
- hash.addData(reinterpret_cast<const char *>(&value), sizeof(value));
}
QString FakeMetaEnum::describe(int baseIndent) const
@@ -84,16 +80,14 @@ QString FakeMetaEnum::describe(int baseIndent) const
QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
QString res = QLatin1String("Enum ");
res += name();
- res += QLatin1String(":{");
+ res += QLatin1String(": [");
for (int i = 0; i < keyCount(); ++i) {
res += newLine;
res += QLatin1String(" ");
res += key(i);
- res += QLatin1String(": ");
- res += QString::number(m_values.value(i, -1));
}
res += newLine;
- res += QLatin1Char('}');
+ res += QLatin1Char(']');
return res;
}
diff --git a/tools/qmllint/fakemetaobject.h b/tools/qmllint/fakemetaobject.h
index 4e0ea1f8b3..ae76596343 100644
--- a/tools/qmllint/fakemetaobject.h
+++ b/tools/qmllint/fakemetaobject.h
@@ -46,7 +46,6 @@ namespace LanguageUtils {
class FakeMetaEnum {
QString m_name;
QStringList m_keys;
- QList<int> m_values;
public:
FakeMetaEnum();
@@ -57,7 +56,7 @@ public:
QString name() const;
void setName(const QString &name);
- void addKey(const QString &key, int value);
+ void addKey(const QString &key);
QString key(int index) const;
int keyCount() const;
QStringList keys() const;
diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp
index 27939608d7..ee2a0c38c1 100644
--- a/tools/qmllint/findunqualified.cpp
+++ b/tools/qmllint/findunqualified.cpp
@@ -39,10 +39,18 @@
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qv4codegen_p.h>
+#include <private/qqmldirparser_p.h>
-QDebug operator<<(QDebug dbg, const QQmlJS::AST::SourceLocation &loc);
+static QQmlDirParser createQmldirParserForFile(const QString &filename)
+{
+ QFile f(filename);
+ f.open(QFile::ReadOnly);
+ QQmlDirParser parser;
+ parser.parse(f.readAll());
+ return parser;
+}
-static QQmlJS::TypeDescriptionReader createReaderForFile(QString const &filename)
+static QQmlJS::TypeDescriptionReader createQmltypesReaderForFile(QString const &filename)
{
QFile f(filename);
f.open(QFile::ReadOnly);
@@ -60,13 +68,12 @@ void FindUnqualifiedIDVisitor::leaveEnvironment()
m_currentScope = m_currentScope->parentScope();
}
-enum ImportVersion { FullyVersioned, PartiallyVersioned, Unversioned };
+enum ImportVersion { FullyVersioned, PartiallyVersioned, Unversioned, BasePath };
-QStringList completeQmltypesPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin)
+QStringList completeImportPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin)
{
static const QLatin1Char Slash('/');
static const QLatin1Char Backslash('\\');
- static const QLatin1String SlashPluginsDotQmltypes("/plugins.qmltypes");
const QVector<QStringRef> parts = uri.splitRef(QLatin1Char('.'), QString::SkipEmptyParts);
@@ -96,7 +103,7 @@ QStringList completeQmltypesPaths(const QString &uri, const QStringList &basePat
return str;
};
- for (int version = FullyVersioned; version <= Unversioned; ++version) {
+ for (int version = FullyVersioned; version <= BasePath; ++version) {
const QString ver = versionString(vmaj, vmin, static_cast<ImportVersion>(version));
for (const QString &path : basePaths) {
@@ -104,20 +111,23 @@ QStringList completeQmltypesPaths(const QString &uri, const QStringList &basePat
if (!dir.endsWith(Slash) && !dir.endsWith(Backslash))
dir += Slash;
- // append to the end
- qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + SlashPluginsDotQmltypes;
+ if (version == BasePath) {
+ qmlDirPathsPaths += dir;
+ } else {
+ // append to the end
+ qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver;
+ }
- if (version != Unversioned) {
+ if (version < Unversioned) {
// insert in the middle
for (int index = parts.count() - 2; index >= 0; --index) {
qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash)
+ ver + Slash
- + joinStringRefs(parts.mid(index + 1), Slash) + SlashPluginsDotQmltypes;
+ + joinStringRefs(parts.mid(index + 1), Slash);
}
}
}
}
-
return qmlDirPathsPaths;
}
@@ -130,19 +140,50 @@ void FindUnqualifiedIDVisitor::importHelper(QString id, QString prefix, int majo
m_alreadySeenImports.insert(importId);
}
id = id.replace(QLatin1String("/"), QLatin1String("."));
- auto qmltypesPaths = completeQmltypesPaths(id, m_qmltypeDirs, major, minor);
+ auto qmltypesPaths = completeImportPaths(id, m_qmltypeDirs, major, minor);
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> objects;
QList<QQmlJS::ModuleApiInfo> moduleApis;
QStringList dependencies;
+ static const QLatin1String SlashPluginsDotQmltypes("/plugins.qmltypes");
+ static const QLatin1String SlashQmldir("/qmldir");
for (auto const &qmltypesPath : qmltypesPaths) {
- if (QFile::exists(qmltypesPath)) {
- auto reader = createReaderForFile(qmltypesPath);
- auto succ = reader(&objects, &moduleApis, &dependencies);
- if (!succ) {
- qDebug() << reader.errorMessage();
+ if (QFile::exists(qmltypesPath + SlashQmldir)) {
+ auto reader = createQmldirParserForFile(qmltypesPath + SlashQmldir);
+ const auto imports = reader.imports();
+ for (const QString &import : imports)
+ importHelper(import, prefix, major, minor);
+
+ QHash<QString, LanguageUtils::FakeMetaObject *> qmlComponents;
+ const auto components = reader.components();
+ for (auto it = components.begin(), end = components.end(); it != end; ++it) {
+ const QString filePath = qmltypesPath + QLatin1Char('/') + it->fileName;
+ if (!QFile::exists(filePath)) {
+ m_colorOut.write(QLatin1String("warning: "), Warning);
+ m_colorOut.write(it->fileName + QLatin1String(" is listed as component in ")
+ + qmltypesPath + SlashQmldir
+ + QLatin1String(" but does not exist.\n"));
+ continue;
+ }
+
+ auto mo = qmlComponents.find(it.key());
+ if (mo == qmlComponents.end())
+ mo = qmlComponents.insert(it.key(), localQmlFile2FakeMetaObject(filePath));
+
+ (*mo)->addExport(
+ it.key(), reader.typeNamespace(),
+ LanguageUtils::ComponentVersion(it->majorVersion, it->minorVersion));
}
- break;
+ for (auto it = qmlComponents.begin(), end = qmlComponents.end(); it != end; ++it) {
+ objects.insert(it.key(),
+ QSharedPointer<const LanguageUtils::FakeMetaObject>(it.value()));
+ }
+ }
+ if (QFile::exists(qmltypesPath + SlashPluginsDotQmltypes)) {
+ auto reader = createQmltypesReaderForFile(qmltypesPath + SlashPluginsDotQmltypes);
+ auto succ = reader(&objects, &moduleApis, &dependencies);
+ if (!succ)
+ m_colorOut.writeUncolored(reader.errorMessage());
}
}
for (auto const &dependency : qAsConst(dependencies)) {
@@ -170,7 +211,8 @@ FindUnqualifiedIDVisitor::localQmlFile2FakeMetaObject(QString filePath)
{
using namespace QQmlJS::AST;
auto fake = new LanguageUtils::FakeMetaObject;
- fake->setClassName(QFileInfo { filePath }.baseName());
+ QString baseName = QFileInfo { filePath }.baseName();
+ fake->setClassName(baseName.endsWith(".ui") ? baseName.chopped(3) : baseName);
QFile file(filePath);
if (!file.open(QFile::ReadOnly)) {
return fake;
@@ -273,6 +315,7 @@ FindUnqualifiedIDVisitor::localQmlFile2FakeMetaObject(QString filePath)
auto sourceElement = static_cast<UiSourceElement *>(initMembers->member);
if (FunctionExpression *fexpr = sourceElement->sourceElement->asFunctionDefinition()) {
LanguageUtils::FakeMetaMethod method;
+ method.setMethodName(fexpr->name.toString());
method.setMethodType(LanguageUtils::FakeMetaMethod::Method);
FormalParameterList *parameters = fexpr->formals;
while (parameters) {
@@ -290,13 +333,17 @@ FindUnqualifiedIDVisitor::localQmlFile2FakeMetaObject(QString filePath)
} else if (cast<VariableStatement *>(sourceElement->sourceElement)) {
// nothing to do
} else {
- qDebug() << "unsupportedd sourceElement at" << sourceElement->firstSourceLocation()
- << sourceElement->sourceElement->kind;
+ const auto loc = sourceElement->firstSourceLocation();
+ m_colorOut.writeUncolored(
+ "unsupportedd sourceElement at "
+ + QString::fromLatin1("%1:%2: ").arg(loc.startLine).arg(loc.startColumn)
+ + QString::number(sourceElement->sourceElement->kind));
}
break;
}
default: {
- qDebug() << "unsupported element of kind" << initMembers->member->kind;
+ m_colorOut.writeUncolored("unsupported element of kind "
+ + QString::number(initMembers->member->kind));
}
}
initMembers = initMembers->next;
@@ -304,6 +351,22 @@ FindUnqualifiedIDVisitor::localQmlFile2FakeMetaObject(QString filePath)
return fake;
}
+void FindUnqualifiedIDVisitor::importDirectory(const QString &directory, const QString &prefix)
+{
+ QString dirname = directory;
+ QFileInfo info { dirname };
+ if (info.isRelative())
+ dirname = QDir(QFileInfo { m_filePath }.path()).filePath(dirname);
+
+ QDirIterator it { dirname, QStringList() << QLatin1String("*.qml"), QDir::NoFilter };
+ while (it.hasNext()) {
+ LanguageUtils::FakeMetaObject *fake = localQmlFile2FakeMetaObject(it.next());
+ m_exportedName2MetaObject.insert(
+ prefix + fake->className(),
+ QSharedPointer<const LanguageUtils::FakeMetaObject>(fake));
+ }
+}
+
void FindUnqualifiedIDVisitor::importExportedNames(QStringRef prefix, QString name)
{
for (;;) {
@@ -348,11 +411,10 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiProgram *)
QDirIterator it { dir, QStringList() << QLatin1String("builtins.qmltypes"), QDir::NoFilter,
QDirIterator::Subdirectories };
while (it.hasNext()) {
- auto reader = createReaderForFile(it.next());
+ auto reader = createQmltypesReaderForFile(it.next());
auto succ = reader(&objects, &moduleApis, &dependencies);
- if (!succ) {
- qDebug() << reader.errorMessage();
- }
+ if (!succ)
+ m_colorOut.writeUncolored(reader.errorMessage());
}
}
// add builtins
@@ -377,6 +439,8 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiProgram *)
meta->addProperty(LanguageUtils::FakeMetaProperty {"ignoreUnknownSignals", "bool", false, false, false, 0});
meta->addProperty(LanguageUtils::FakeMetaProperty {"target", "QObject", false, false, false, 0});
m_exportedName2MetaObject["Connections"] = LanguageUtils::FakeMetaObject::ConstPtr { meta };
+
+ importDirectory(".", QString());
return true;
}
@@ -476,6 +540,23 @@ void FindUnqualifiedIDVisitor::endVisit(QQmlJS::AST::WithStatement *)
leaveEnvironment();
}
+static QString signalName(const QStringRef &handlerName)
+{
+ if (handlerName.startsWith("on") && handlerName.size() > 2) {
+ QString signal = handlerName.mid(2).toString();
+ for (int i = 0; i < signal.length(); ++i) {
+ QCharRef ch = signal[i];
+ if (ch.isLower())
+ return QString();
+ if (ch.isUpper()) {
+ ch = ch.toLower();
+ return signal;
+ }
+ }
+ }
+ return QString();
+}
+
bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiScriptBinding *uisb)
{
using namespace QQmlJS::AST;
@@ -489,8 +570,17 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiScriptBinding *uisb)
if (m_currentScope->isVisualRootScope()) {
m_rootId = identexp->name.toString();
}
- } else if (name.startsWith("on") && name.size() > 2 && name.at(2).isUpper()) {
- auto statement = uisb->statement;
+ } else {
+ const QString signal = signalName(name);
+ if (signal.isEmpty())
+ return true;
+
+ if (!m_currentScope->methods().contains(signal)) {
+ m_currentScope->addUnmatchedSignalHandler(name.toString(), uisb->firstSourceLocation());
+ return true;
+ }
+
+ const auto statement = uisb->statement;
if (statement->kind == Node::Kind::Kind_ExpressionStatement) {
if (static_cast<ExpressionStatement *>(statement)->expression->asFunctionDefinition()) {
// functions are already handled
@@ -499,17 +589,14 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiScriptBinding *uisb)
return true;
}
}
- QString signal = name.mid(2).toString();
- signal[0] = signal[0].toLower();
- if (!m_currentScope->methods().contains(signal)) {
- qDebug() << "Info file does not contain signal" << signal;
- } else {
- auto method = m_currentScope->methods()[signal];
- for (auto const &param : method.parameterNames()) {
- auto firstSourceLocation = uisb->statement->firstSourceLocation();
- bool hasMultilineStatementBody = uisb->statement->lastSourceLocation().startLine > firstSourceLocation.startLine;
- m_currentScope->insertSignalIdentifier(param, method, firstSourceLocation, hasMultilineStatementBody);
- }
+
+ auto method = m_currentScope->methods()[signal];
+ for (auto const &param : method.parameterNames()) {
+ const auto firstSourceLocation = statement->firstSourceLocation();
+ bool hasMultilineStatementBody
+ = statement->lastSourceLocation().startLine > firstSourceLocation.startLine;
+ m_currentScope->insertSignalIdentifier(param, method, firstSourceLocation,
+ hasMultilineStatementBody);
}
return true;
}
@@ -535,13 +622,15 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::IdentifierExpression *idexp)
}
FindUnqualifiedIDVisitor::FindUnqualifiedIDVisitor(QStringList const &qmltypeDirs,
- const QString &code, const QString &fileName)
+ const QString &code, const QString &fileName,
+ bool silent)
: m_rootScope(new ScopeTree { ScopeType::JSFunctionScope, "global" }),
m_currentScope(m_rootScope.get()),
m_qmltypeDirs(qmltypeDirs),
m_code(code),
m_rootId(QLatin1String("<id>")),
- m_filePath(fileName)
+ m_filePath(fileName),
+ m_colorOut(silent)
{
// setup color output
m_colorOut.insertColorMapping(Error, ColorOutput::RedForeground);
@@ -649,18 +738,9 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiImport *import)
prefix += import->importId + QLatin1Char('.');
}
auto dirname = import->fileName.toString();
- if (!dirname.isEmpty()) {
- QFileInfo info { dirname };
- if (info.isRelative()) {
- dirname = QDir(QFileInfo { m_filePath }.path()).filePath(dirname);
- }
- QDirIterator it { dirname, QStringList() << QLatin1String("*.qml"), QDir::NoFilter };
- while (it.hasNext()) {
- LanguageUtils::FakeMetaObject *fake = localQmlFile2FakeMetaObject(it.next());
- m_exportedName2MetaObject.insert(
- fake->className(), QSharedPointer<const LanguageUtils::FakeMetaObject>(fake));
- }
- }
+ if (!dirname.isEmpty())
+ importDirectory(dirname, prefix);
+
QString path {};
if (!import->importId.isEmpty()) {
m_qmlid2meta.insert(import->importId.toString(), {}); // TODO: do not put imported ids into the same space as qml IDs
@@ -768,16 +848,19 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiObjectDefinition *uiod)
return true;
}
-void FindUnqualifiedIDVisitor::endVisit(QQmlJS::AST::UiObjectDefinition *)
+bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::PatternElement *element)
{
- leaveEnvironment();
+ if (element->isVariableDeclaration()) {
+ QQmlJS::AST::BoundNames names;
+ element->boundNames(&names);
+ for (const auto &name : names)
+ m_currentScope->insertJSIdentifier(name.id, element->scope);
+ }
+
+ return true;
}
-QDebug operator<<(QDebug dbg, const QQmlJS::AST::SourceLocation &loc)
+void FindUnqualifiedIDVisitor::endVisit(QQmlJS::AST::UiObjectDefinition *)
{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << loc.startLine;
- dbg.nospace() << ":";
- dbg.nospace() << loc.startColumn;
- return dbg.maybeSpace();
+ leaveEnvironment();
}
diff --git a/tools/qmllint/findunqualified.h b/tools/qmllint/findunqualified.h
index 181f42f265..80413bd402 100644
--- a/tools/qmllint/findunqualified.h
+++ b/tools/qmllint/findunqualified.h
@@ -43,7 +43,8 @@ enum class ScopeType;
class FindUnqualifiedIDVisitor : public QQmlJS::AST::Visitor {
public:
- explicit FindUnqualifiedIDVisitor(QStringList const &qmltypeDirs, const QString& code, const QString& fileName);
+ explicit FindUnqualifiedIDVisitor(QStringList const &qmltypeDirs, const QString& code,
+ const QString& fileName, bool silent);
~FindUnqualifiedIDVisitor() override;
bool check();
@@ -70,7 +71,7 @@ private:
void importHelper(QString id, QString prefix, int major, int minor);
LanguageUtils::FakeMetaObject* localQmlFile2FakeMetaObject(QString filePath);
-
+ void importDirectory(const QString &directory, const QString &prefix);
void importExportedNames(QStringRef prefix, QString name);
void throwRecursionDepthError() override;
@@ -125,6 +126,8 @@ private:
// expression handling
bool visit(QQmlJS::AST::IdentifierExpression *idexp) override;
+
+ bool visit(QQmlJS::AST::PatternElement *) override;
};
diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp
index 235ec16c6e..56f72dd020 100644
--- a/tools/qmllint/main.cpp
+++ b/tools/qmllint/main.cpp
@@ -50,7 +50,8 @@ static bool lint_file(const QString &filename, const bool silent, const bool war
{
QFile file(filename);
if (!file.open(QFile::ReadOnly)) {
- qWarning() << "Failed to open file" << filename << file.error();
+ if (!silent)
+ qWarning() << "Failed to open file" << filename << file.error();
return false;
}
@@ -76,7 +77,7 @@ static bool lint_file(const QString &filename, const bool silent, const bool war
if (success && !isJavaScript && warnUnqualied) {
auto root = parser.rootNode();
- FindUnqualifiedIDVisitor v { qmltypeDirs, code, filename};
+ FindUnqualifiedIDVisitor v { qmltypeDirs, code, filename, silent };
root->accept(&v);
success = v.check();
}
@@ -122,9 +123,9 @@ int main(int argv, char *argc[])
// use host qml import path as a sane default if nothing else has been provided
QStringList qmltypeDirs = parser.isSet(qmltypesDirsOption) ? parser.values(qmltypesDirsOption)
#ifndef QT_BOOTSTRAPPED
- : QStringList{QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)};
+ : QStringList{QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath), QLatin1String(".")};
#else
- : QStringList{};
+ : QStringList{QLatin1String(".")};
#endif
#else
bool silent = false;
diff --git a/tools/qmllint/qcoloroutput.cpp b/tools/qmllint/qcoloroutput.cpp
index d2e723700a..eb4c721663 100644
--- a/tools/qmllint/qcoloroutput.cpp
+++ b/tools/qmllint/qcoloroutput.cpp
@@ -39,7 +39,7 @@
class ColorOutputPrivate
{
public:
- ColorOutputPrivate() : currentColorID(-1)
+ ColorOutputPrivate(bool silent) : currentColorID(-1), silent(silent)
{
/* - QIODevice::Unbuffered because we want it to appear when the user actually calls, performance
@@ -53,6 +53,7 @@ public:
ColorOutput::ColorMapping colorMapping;
int currentColorID;
bool coloringEnabled;
+ bool silent;
static const char *const foregrounds[];
static const char *const backgrounds[];
@@ -238,7 +239,7 @@ ColorOutput::ColorMapping ColorOutput::colorMapping() const
/*!
Constructs a ColorOutput instance, ready for use.
*/
-ColorOutput::ColorOutput() : d(new ColorOutputPrivate())
+ColorOutput::ColorOutput(bool silent) : d(new ColorOutputPrivate(silent))
{
}
@@ -258,7 +259,8 @@ ColorOutput::~ColorOutput() = default; // must be here so that QScopedPointer ha
*/
void ColorOutput::write(const QString &message, int colorID)
{
- d->write(colorify(message, colorID));
+ if (!d->silent)
+ d->write(colorify(message, colorID));
}
/*!
@@ -269,7 +271,8 @@ void ColorOutput::write(const QString &message, int colorID)
*/
void ColorOutput::writeUncolored(const QString &message)
{
- d->write(message + QLatin1Char('\n'));
+ if (!d->silent)
+ d->write(message + QLatin1Char('\n'));
}
/*!
diff --git a/tools/qmllint/qcoloroutput_p.h b/tools/qmllint/qcoloroutput_p.h
index 710bf5db74..aefa765a87 100644
--- a/tools/qmllint/qcoloroutput_p.h
+++ b/tools/qmllint/qcoloroutput_p.h
@@ -89,7 +89,7 @@ public:
typedef QFlags<ColorCodeComponent> ColorCode;
typedef QHash<int, ColorCode> ColorMapping;
- ColorOutput();
+ ColorOutput(bool silent);
~ColorOutput();
void setColorMapping(const ColorMapping &cMapping);
diff --git a/tools/qmllint/qmljstypedescriptionreader.cpp b/tools/qmllint/qmljstypedescriptionreader.cpp
index 542cdf99eb..b8aecdddb1 100644
--- a/tools/qmllint/qmljstypedescriptionreader.cpp
+++ b/tools/qmllint/qmljstypedescriptionreader.cpp
@@ -123,15 +123,13 @@ void TypeDescriptionReader::readDocument(UiProgram *ast)
return;
}
- ComponentVersion version;
- const QString versionString = _source.mid(import->versionToken.offset, import->versionToken.length);
- const int dotIdx = versionString.indexOf(QLatin1Char('.'));
- if (dotIdx != -1) {
- version = ComponentVersion(versionString.leftRef(dotIdx).toInt(),
- versionString.midRef(dotIdx + 1).toInt());
- }
- if (version.majorVersion() != 1) {
- addError(import->versionToken, tr("Major version different from 1 not supported."));
+ if (!import->version) {
+ addError(import->firstSourceLocation(), tr("Import statement without version."));
+ return;
+ }
+
+ if (import->version->majorVersion != 1) {
+ addError(import->version->firstSourceLocation(), tr("Major version different from 1 not supported."));
return;
}
@@ -666,39 +664,34 @@ void TypeDescriptionReader::readEnumValues(AST::UiScriptBinding *ast, LanguageUt
return;
}
- ExpressionStatement *expStmt = AST::cast<ExpressionStatement *>(ast->statement);
+ auto *expStmt = AST::cast<ExpressionStatement *>(ast->statement);
if (!expStmt) {
- addError(ast->statement->firstSourceLocation(), tr("Expected object literal after colon."));
+ addError(ast->statement->firstSourceLocation(), tr("Expected expression after colon."));
return;
}
- ObjectPattern *objectLit = AST::cast<ObjectPattern *>(expStmt->expression);
- if (!objectLit) {
- addError(expStmt->firstSourceLocation(), tr("Expected object literal after colon."));
- return;
- }
-
- for (PatternPropertyList *it = objectLit->properties; it; it = it->next) {
- PatternProperty *assignement = AST::cast<PatternProperty *>(it->property);
- if (assignement) {
- StringLiteralPropertyName *propName = AST::cast<StringLiteralPropertyName *>(assignement->name);
- NumericLiteral *value = AST::cast<NumericLiteral *>(assignement->initializer);
- UnaryMinusExpression *minus = AST::cast<UnaryMinusExpression *>(assignement->initializer);
- if (minus)
- value = AST::cast<NumericLiteral *>(minus->expression);
- if (!propName || !value) {
- addError(objectLit->firstSourceLocation(), tr("Expected object literal to contain only 'string: number' elements."));
- continue;
+ if (auto *objectLit = AST::cast<ObjectPattern *>(expStmt->expression)) {
+ for (PatternPropertyList *it = objectLit->properties; it; it = it->next) {
+ if (PatternProperty *assignement = it->property) {
+ if (auto *name = AST::cast<StringLiteralPropertyName *>(assignement->name)) {
+ fme->addKey(name->id.toString());
+ continue;
+ }
}
-
- double v = value->value;
- if (minus)
- v = -v;
- fme->addKey(propName->id.toString(), v);
- continue;
+ addError(it->firstSourceLocation(), tr("Expected strings as enum keys."));
+ }
+ } else if (auto *arrayLit = AST::cast<ArrayPattern *>(expStmt->expression)) {
+ for (PatternElementList *it = arrayLit->elements; it; it = it->next) {
+ if (PatternElement *element = it->element) {
+ if (auto *name = AST::cast<StringLiteral *>(element->initializer)) {
+ fme->addKey(name->value.toString());
+ continue;
+ }
+ }
+ addError(it->firstSourceLocation(), tr("Expected strings as enum keys."));
}
- PatternPropertyList *getterSetter = AST::cast<PatternPropertyList *>(it->next);
- if (getterSetter)
- addError(objectLit->firstSourceLocation(), tr("Enum should not contain getter and setters, but only 'string: number' elements."));
+ } else {
+ addError(ast->statement->firstSourceLocation(),
+ tr("Expected either array or object literal as enum definition."));
}
}
diff --git a/tools/qmllint/scopetree.cpp b/tools/qmllint/scopetree.cpp
index 2eff3fa319..1e873cca8f 100644
--- a/tools/qmllint/scopetree.cpp
+++ b/tools/qmllint/scopetree.cpp
@@ -81,6 +81,12 @@ void ScopeTree::insertPropertyIdentifier(QString id)
this->addMethod(method);
}
+void ScopeTree::addUnmatchedSignalHandler(const QString &handler,
+ const QQmlJS::AST::SourceLocation &location)
+{
+ m_unmatchedSignalHandlers.append(qMakePair(handler, location));
+}
+
bool ScopeTree::isIdInCurrentScope(const QString &id) const
{
return isIdInCurrentQMlScopes(id) || isIdInCurrentJSScopes(id);
@@ -132,6 +138,15 @@ bool ScopeTree::recheckIdentifiers(const QString& code, const QHash<QString, Lan
workQueue.enqueue(this);
while (!workQueue.empty()) {
const ScopeTree* currentScope = workQueue.dequeue();
+ for (const auto &handler : currentScope->m_unmatchedSignalHandlers) {
+ colorOut.write("Warning: ", Warning);
+ colorOut.write(QString::fromLatin1(
+ "no matching signal found for handler \"%1\" at %2:%3\n")
+ .arg(handler.first).arg(handler.second.startLine)
+ .arg(handler.second.startColumn), Normal);
+ printContext(colorOut, code, handler.second);
+ }
+
for (auto idLocationPair : currentScope->m_accessedIdentifiers) {
if (qmlIDs.contains(idLocationPair.first))
continue;
@@ -141,13 +156,11 @@ bool ScopeTree::recheckIdentifiers(const QString& code, const QHash<QString, Lan
noUnqualifiedIdentifier = false;
colorOut.write("Warning: ", Warning);
auto location = idLocationPair.second;
- colorOut.write(QString::asprintf("unqualified access at %d:%d\n", location.startLine, location.startColumn), Normal);
- IssueLocationWithContext issueLocationWithContext {code, location};
- colorOut.write(issueLocationWithContext.beforeText.toString(), Normal);
- colorOut.write(issueLocationWithContext.issueText.toString(), Error);
- colorOut.write(issueLocationWithContext.afterText.toString() + QLatin1Char('\n'), Normal);
- int tabCount = issueLocationWithContext.beforeText.count(QLatin1Char('\t'));
- colorOut.write(QString(" ").repeated(issueLocationWithContext.beforeText.length() - tabCount) + QString("\t").repeated(tabCount) + QString("^").repeated(location.length) + QLatin1Char('\n'), Normal);
+ colorOut.write(QString::asprintf("unqualified access at %d:%d\n", location.startLine,
+ location.startColumn), Normal);
+
+ printContext(colorOut, code, location);
+
// root(JS) --> program(qml) --> (first element)
if (root->m_childScopes[0]->m_childScopes[0]->m_currentScopeQMLIdentifiers.contains(idLocationPair.first)) {
ScopeTree *parentScope = currentScope->m_parentScope;
@@ -161,6 +174,7 @@ bool ScopeTree::recheckIdentifiers(const QString& code, const QHash<QString, Lan
colorOut.write("Note: ", Warning);
colorOut.write(("You first have to give the root element an id\n"));
}
+ IssueLocationWithContext issueLocationWithContext {code, location};
colorOut.write(issueLocationWithContext.beforeText.toString(), Normal);
colorOut.write(rootId + QLatin1Char('.'), Hint);
colorOut.write(issueLocationWithContext.issueText.toString(), Normal);
@@ -212,7 +226,7 @@ QMap<QString, LanguageUtils::FakeMetaMethod>const &ScopeTree::methods() const
bool ScopeTree::isIdInCurrentQMlScopes(QString id) const
{
auto qmlScope = getCurrentQMLScope();
- return qmlScope->m_currentScopeQMLIdentifiers.contains(id);
+ return qmlScope->m_currentScopeQMLIdentifiers.contains(id) || qmlScope->m_methods.contains(id);
}
bool ScopeTree::isIdInCurrentJSScopes(QString id) const
@@ -250,6 +264,20 @@ ScopeTree *ScopeTree::getCurrentQMLScope()
return qmlScope;
}
+void ScopeTree::printContext(ColorOutput &colorOut, const QString &code,
+ const QQmlJS::AST::SourceLocation &location) const
+{
+ IssueLocationWithContext issueLocationWithContext {code, location};
+ colorOut.write(issueLocationWithContext.beforeText.toString(), Normal);
+ colorOut.write(issueLocationWithContext.issueText.toString(), Error);
+ colorOut.write(issueLocationWithContext.afterText.toString() + QLatin1Char('\n'), Normal);
+ int tabCount = issueLocationWithContext.beforeText.count(QLatin1Char('\t'));
+ colorOut.write(QString(" ").repeated(issueLocationWithContext.beforeText.length() - tabCount)
+ + QString("\t").repeated(tabCount)
+ + QString("^").repeated(location.length)
+ + QLatin1Char('\n'), Normal);
+}
+
ScopeType ScopeTree::scopeType() {return m_scopeType;}
void ScopeTree::addMethod(LanguageUtils::FakeMetaMethod method)
diff --git a/tools/qmllint/scopetree.h b/tools/qmllint/scopetree.h
index 872a509123..52cdc45e96 100644
--- a/tools/qmllint/scopetree.h
+++ b/tools/qmllint/scopetree.h
@@ -73,6 +73,8 @@ public:
void insertQMLIdentifier(QString id);
void insertSignalIdentifier(QString id, LanguageUtils::FakeMetaMethod method, QQmlJS::AST::SourceLocation loc, bool hasMultilineHandlerBody);
void insertPropertyIdentifier(QString id); // inserts property as qml identifier as well as the corresponding
+ void addUnmatchedSignalHandler(const QString &handler,
+ const QQmlJS::AST::SourceLocation &location);
bool isIdInCurrentScope(QString const &id) const;
void addIdToAccssedIfNotInParentScopes(QPair<QString, QQmlJS::AST::SourceLocation> const& id_loc_pair, const QSet<QString>& unknownImports);
@@ -96,11 +98,14 @@ private:
ScopeTree *m_parentScope;
QString m_name;
ScopeType m_scopeType;
+ QVector<QPair<QString, QQmlJS::AST::SourceLocation>> m_unmatchedSignalHandlers;
bool isIdInCurrentQMlScopes(QString id) const;
bool isIdInCurrentJSScopes(QString id) const;
bool isIdInjectedFromSignal(QString id) const;
const ScopeTree* getCurrentQMLScope() const;
ScopeTree* getCurrentQMLScope();
+ void printContext(ColorOutput& colorOut, const QString &code,
+ const QQmlJS::AST::SourceLocation &location) const;
};
#endif // SCOPETREE_H
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index f0ed1f8ebe..5e999c557a 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -105,12 +105,18 @@ struct QmlVersionInfo
QString pluginImportUri;
int majorVersion;
int minorVersion;
+ bool strict;
};
static bool matchingImportUri(const QQmlType &ty, const QmlVersionInfo& versionInfo) {
- return (versionInfo.pluginImportUri == ty.module()
- && (ty.majorVersion() == versionInfo.majorVersion || ty.majorVersion() == -1))
- || ty.module().isEmpty();
+ if (versionInfo.strict) {
+ return (versionInfo.pluginImportUri == ty.module()
+ && (ty.majorVersion() == versionInfo.majorVersion || ty.majorVersion() == -1))
+ || ty.module().isEmpty();
+ }
+ return ty.module().isEmpty()
+ || versionInfo.pluginImportUri == ty.module()
+ || ty.module().startsWith(versionInfo.pluginImportUri + QLatin1Char('.'));
}
void collectReachableMetaObjects(const QMetaObject *meta, QSet<const QMetaObject *> *metas, const QmlVersionInfo &info, bool extended = false, bool alreadyChangedModule = false)
@@ -230,14 +236,14 @@ QByteArray convertToId(const QMetaObject *mo)
// Collect all metaobjects for types registered with qmlRegisterType() without parameters
void collectReachableMetaObjectsWithoutQmlName(QQmlEnginePrivate *engine, QSet<const QMetaObject *>& metas,
- QMap<QString, QSet<QQmlType>> &compositeTypes, const QmlVersionInfo &info) {
+ QMap<QString, QList<QQmlType>> &compositeTypes, const QmlVersionInfo &info) {
const auto qmlAllTypes = QQmlMetaType::qmlAllTypes();
for (const QQmlType &ty : qmlAllTypes) {
if (!metas.contains(ty.baseMetaObject())) {
if (!ty.isComposite()) {
collectReachableMetaObjects(engine, ty, &metas, info);
} else if (matchingImportUri(ty, info)) {
- compositeTypes[ty.elementName()].insert(ty);
+ compositeTypes[ty.elementName()].append(ty);
}
}
}
@@ -246,7 +252,7 @@ void collectReachableMetaObjectsWithoutQmlName(QQmlEnginePrivate *engine, QSet<c
QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
QSet<const QMetaObject *> &noncreatables,
QSet<const QMetaObject *> &singletons,
- QMap<QString, QSet<QQmlType>> &compositeTypes,
+ QMap<QString, QList<QQmlType>> &compositeTypes,
const QmlVersionInfo &info,
const QList<QQmlType> &skip = QList<QQmlType>()
)
@@ -266,7 +272,7 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
qmlTypesByCppName[ty.baseMetaObject()->className()].insert(ty);
collectReachableMetaObjects(QQmlEnginePrivate::get(engine), ty, &metas, info);
} else {
- compositeTypes[ty.elementName()].insert(ty);
+ compositeTypes[ty.elementName()].append(ty);
}
}
@@ -436,10 +442,11 @@ public:
}
QString getPrototypeNameForCompositeType(const QMetaObject *metaObject, QSet<QByteArray> &defaultReachableNames,
- QList<const QMetaObject *> *objectsToMerge)
+ QList<const QMetaObject *> *objectsToMerge, const QmlVersionInfo &versionInfo)
{
+ auto ty = QQmlMetaType::qmlType(metaObject);
QString prototypeName;
- if (!defaultReachableNames.contains(metaObject->className())) {
+ if (matchingImportUri(ty, versionInfo)) {
// dynamic meta objects can break things badly
// but extended types are usually fine
const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate *>(metaObject->d.data);
@@ -451,20 +458,20 @@ public:
prototypeName = "QObject";
else
prototypeName = getPrototypeNameForCompositeType(
- superMetaObject, defaultReachableNames, objectsToMerge);
+ superMetaObject, defaultReachableNames, objectsToMerge, versionInfo);
} else {
prototypeName = convertToId(metaObject->className());
}
return prototypeName;
}
- void dumpComposite(QQmlEngine *engine, const QSet<QQmlType> &compositeType, QSet<QByteArray> &defaultReachableNames)
+ void dumpComposite(QQmlEngine *engine, const QList<QQmlType> &compositeType, QSet<QByteArray> &defaultReachableNames, const QmlVersionInfo &versionInfo)
{
for (const QQmlType &type : compositeType)
- dumpCompositeItem(engine, type, defaultReachableNames);
+ dumpCompositeItem(engine, type, defaultReachableNames, versionInfo);
}
- void dumpCompositeItem(QQmlEngine *engine, const QQmlType &compositeType, QSet<QByteArray> &defaultReachableNames)
+ void dumpCompositeItem(QQmlEngine *engine, const QQmlType &compositeType, QSet<QByteArray> &defaultReachableNames, const QmlVersionInfo &versionInfo)
{
QQmlComponent e(engine, compositeType.sourceUrl());
if (!e.isReady()) {
@@ -486,7 +493,7 @@ public:
KnownAttributes knownAttributes;
// Get C++ base class name for the composite type
QString prototypeName = getPrototypeNameForCompositeType(mainMeta, defaultReachableNames,
- &objectsToMerge);
+ &objectsToMerge, versionInfo);
qml->writeScriptBinding(QLatin1String("prototype"), enquote(prototypeName));
QString qmlTyName = compositeType.qmlTypeName();
@@ -991,6 +998,16 @@ void printDebugMessage(QtMsgType, const QMessageLogContext &, const QString &msg
// In case of QtFatalMsg the calling code will abort() when appropriate.
}
+QT_BEGIN_NAMESPACE
+static bool operator<(const QQmlType &a, const QQmlType &b)
+{
+ return a.qmlTypeName() < b.qmlTypeName()
+ || (a.qmlTypeName() == b.qmlTypeName()
+ && ((a.majorVersion() < b.majorVersion())
+ || (a.majorVersion() == b.majorVersion()
+ && a.minorVersion() < b.minorVersion())));
+}
+QT_END_NAMESPACE
int main(int argc, char *argv[])
{
@@ -1056,6 +1073,7 @@ int main(int argc, char *argv[])
QString dependenciesFile;
QString mergeFile;
bool forceQtQuickDependency = true;
+ bool strict = false;
enum Action { Uri, Path, Builtins };
Action action = Uri;
{
@@ -1120,6 +1138,10 @@ int main(int argc, char *argv[])
} else if (arg == QLatin1String("--qapp")
|| arg == QLatin1String("-qapp")) {
continue;
+ } else if (arg == QLatin1String("--strict")
+ || arg == QLatin1String("-strict")) {
+ strict = true;
+ continue;
} else {
std::cerr << "Invalid argument: " << qPrintable(arg) << std::endl;
return EXIT_INVALIDARGUMENTS;
@@ -1216,7 +1238,6 @@ int main(int argc, char *argv[])
// find all QMetaObjects reachable from the builtin module
QSet<const QMetaObject *> uncreatableMetas;
QSet<const QMetaObject *> singletonMetas;
- QMap<QString, QSet<QQmlType>> defaultCompositeTypes;
// QQuickKeyEvent, QQuickPinchEvent, QQuickDropEvent are not exported
QSet<QByteArray> defaultReachableNames;
@@ -1225,11 +1246,13 @@ int main(int argc, char *argv[])
QSet<const QMetaObject *> metas;
// composite types we want to dump information of
- QMap<QString, QSet<QQmlType>> compositeTypes;
+ QMap<QString, QList<QQmlType>> compositeTypes;
int majorVersion = qtQmlMajorVersion, minorVersion = qtQmlMinorVersion;
+ QmlVersionInfo info;
if (action == Builtins) {
- QSet<const QMetaObject *> builtins = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, defaultCompositeTypes, {QLatin1String("Qt"), majorVersion, minorVersion});
+ QMap<QString, QList<QQmlType>> defaultCompositeTypes;
+ QSet<const QMetaObject *> builtins = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, defaultCompositeTypes, {QLatin1String("Qt"), majorVersion, minorVersion, strict});
Q_ASSERT(builtins.size() == 1);
metas.insert(*builtins.begin());
} else {
@@ -1289,15 +1312,12 @@ int main(int argc, char *argv[])
return EXIT_IMPORTERROR;
}
}
+ info = {pluginImportUri, majorVersion, minorVersion, strict};
+ QSet<const QMetaObject *> candidates = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, compositeTypes, info, defaultTypes);
- QSet<const QMetaObject *> candidates = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, compositeTypes, {pluginImportUri, majorVersion, minorVersion}, defaultTypes);
-
- for (QString iter: compositeTypes.keys()) {
- if (defaultCompositeTypes.contains(iter)) {
- QSet<QQmlType> compositeTypesByName = compositeTypes.value(iter);
- compositeTypesByName.subtract(defaultCompositeTypes.value(iter));
- compositeTypes[iter] = compositeTypesByName;
- }
+ for (auto it = compositeTypes.begin(), end = compositeTypes.end(); it != end; ++it) {
+ std::sort(it->begin(), it->end());
+ it->erase(std::unique(it->begin(), it->end()), it->end());
}
for (const QMetaObject *mo : qAsConst(candidates)) {
@@ -1348,9 +1368,9 @@ int main(int argc, char *argv[])
dumper.dump(QQmlEnginePrivate::get(&engine), meta, uncreatableMetas.contains(meta), singletonMetas.contains(meta));
}
- QMap<QString, QSet<QQmlType> >::const_iterator iter = compositeTypes.constBegin();
+ QMap<QString, QList<QQmlType>>::const_iterator iter = compositeTypes.constBegin();
for (; iter != compositeTypes.constEnd(); ++iter)
- dumper.dumpComposite(&engine, iter.value(), defaultReachableNames);
+ dumper.dumpComposite(&engine, iter.value(), defaultReachableNames, info);
// define QEasingCurve as an extension of QQmlEasingValueType, this way
// properties using the QEasingCurve type get useful type information.
diff --git a/tools/qmlplugindump/qmlstreamwriter.cpp b/tools/qmlplugindump/qmlstreamwriter.cpp
index 3632cee60d..b0fbc4e443 100644
--- a/tools/qmlplugindump/qmlstreamwriter.cpp
+++ b/tools/qmlplugindump/qmlstreamwriter.cpp
@@ -50,9 +50,9 @@ void QmlStreamWriter::writeEndDocument()
void QmlStreamWriter::writeLibraryImport(const QString &uri, int majorVersion, int minorVersion, const QString &as)
{
- m_stream->write(QString("import %1 %2.%3").arg(uri, QString::number(majorVersion), QString::number(minorVersion)).toUtf8());
+ m_stream->write(QString::fromLatin1("import %1 %2.%3").arg(uri, QString::number(majorVersion), QString::number(minorVersion)).toUtf8());
if (!as.isEmpty())
- m_stream->write(QString(" as %1").arg(as).toUtf8());
+ m_stream->write(QString::fromLatin1(" as %1").arg(as).toUtf8());
m_stream->write("\n");
}
@@ -60,7 +60,7 @@ void QmlStreamWriter::writeStartObject(const QString &component)
{
flushPotentialLinesWithNewlines();
writeIndent();
- m_stream->write(QString("%1 {").arg(component).toUtf8());
+ m_stream->write(QString::fromLatin1("%1 {").arg(component).toUtf8());
++m_indentDepth;
m_maybeOneline = true;
}
@@ -89,7 +89,7 @@ void QmlStreamWriter::writeEndObject()
void QmlStreamWriter::writeScriptBinding(const QString &name, const QString &rhs)
{
- writePotentialLine(QString("%1: %2").arg(name, rhs).toUtf8());
+ writePotentialLine(QString::fromLatin1("%1: %2").arg(name, rhs).toUtf8());
}
void QmlStreamWriter::writeBooleanBinding(const QString &name, bool value)
@@ -104,7 +104,7 @@ void QmlStreamWriter::writeArrayBinding(const QString &name, const QStringList &
// try to use a single line
QString singleLine;
- singleLine += QString("%1: [").arg(name);
+ singleLine += QString::fromLatin1("%1: [").arg(name);
for (int i = 0; i < elements.size(); ++i) {
singleLine += elements.at(i);
if (i != elements.size() - 1)
@@ -117,7 +117,7 @@ void QmlStreamWriter::writeArrayBinding(const QString &name, const QStringList &
}
// write multi-line
- m_stream->write(QString("%1: [\n").arg(name).toUtf8());
+ m_stream->write(QString::fromLatin1("%1: [\n").arg(name).toUtf8());
++m_indentDepth;
for (int i = 0; i < elements.size(); ++i) {
writeIndent();
@@ -143,13 +143,13 @@ void QmlStreamWriter::writeScriptObjectLiteralBinding(const QString &name, const
{
flushPotentialLinesWithNewlines();
writeIndent();
- m_stream->write(QString("%1: {\n").arg(name).toUtf8());
+ m_stream->write(QString::fromLatin1("%1: {\n").arg(name).toUtf8());
++m_indentDepth;
for (int i = 0; i < keyValue.size(); ++i) {
const QString key = keyValue.at(i).first;
const QString value = keyValue.at(i).second;
writeIndent();
- m_stream->write(QString("%1: %2").arg(key, value).toUtf8());
+ m_stream->write(QString::fromLatin1("%1: %2").arg(key, value).toUtf8());
if (i != keyValue.size() - 1) {
m_stream->write(",\n");
} else {
diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp
index f92ffa9ff5..7b010546c3 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.cpp
+++ b/tools/qmlprofiler/qmlprofilerapplication.cpp
@@ -302,7 +302,7 @@ void QmlProfilerApplication::flush()
{
if (m_recording) {
m_pendingRequest = REQUEST_FLUSH;
- m_qmlProfilerClient->sendRecordingStatus(false);
+ m_qmlProfilerClient->setRecording(false);
} else {
if (m_profilerData->save(m_interactiveOutputFile)) {
m_profilerData->clear();
@@ -392,7 +392,7 @@ void QmlProfilerApplication::userCommand(const QString &command)
if (cmd == Constants::CMD_RECORD || cmd == Constants::CMD_RECORD2) {
m_pendingRequest = REQUEST_TOGGLE_RECORDING;
- m_qmlProfilerClient->sendRecordingStatus(!m_recording);
+ m_qmlProfilerClient->setRecording(!m_recording);
} else if (cmd == Constants::CMD_QUIT || cmd == Constants::CMD_QUIT2) {
m_pendingRequest = REQUEST_QUIT;
if (m_recording) {
diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp
index d5662a0182..9ec143975e 100644
--- a/tools/qmlprofiler/qmlprofilerdata.cpp
+++ b/tools/qmlprofiler/qmlprofilerdata.cpp
@@ -101,7 +101,6 @@ QmlProfilerData::~QmlProfilerData()
void QmlProfilerData::clear()
{
- d->eventTypes.clear();
d->events.clear();
d->traceEndTime = std::numeric_limits<qint64>::min();
diff --git a/tools/qmltime/qmltime.cpp b/tools/qmltime/qmltime.cpp
index 7baedff611..b0761a54d4 100644
--- a/tools/qmltime/qmltime.cpp
+++ b/tools/qmltime/qmltime.cpp
@@ -207,7 +207,7 @@ int main(int argc, char ** argv)
QGuiApplication app(argc, argv);
QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
- qmlRegisterType<Timer>("QmlTime", 1, 0, "Timer");
+ qmlRegisterTypesAndRevisions<Timer>("QmlTime", 1);
uint iterations = 1024;
QString filename;