aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules2
-rw-r--r--.qmake.conf2
-rw-r--r--examples/quick/imageresponseprovider/ImageResponseProviderCore/qmldir2
-rw-r--r--examples/quick/imageresponseprovider/doc/src/imageresponseprovider.qdoc35
-rw-r--r--examples/quick/imageresponseprovider/imageresponseprovider-example.qml48
-rw-r--r--examples/quick/imageresponseprovider/imageresponseprovider.cpp123
-rw-r--r--examples/quick/imageresponseprovider/imageresponseprovider.pro15
-rw-r--r--examples/quick/imageresponseprovider/imageresponseprovider.qmlproject14
-rw-r--r--examples/quick/quick.pro1
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.cpp5
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.h2
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerMIPS.h32
-rw-r--r--src/3rdparty/masm/disassembler/Mips32Disassembler.cpp56
-rw-r--r--src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp620
-rw-r--r--src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h78
-rw-r--r--src/3rdparty/masm/masm-defs.pri1
-rw-r--r--src/3rdparty/masm/masm.pri3
-rw-r--r--src/3rdparty/masm/wtf/Platform.h2
-rw-r--r--src/imports/folderlistmodel/fileinfothread.cpp1
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp14
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.h3
-rw-r--r--src/imports/localstorage/plugin.cpp27
-rw-r--r--src/imports/testlib/TestCase.qml7
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel.cpp2
-rw-r--r--src/particles/qquickcustomparticle.cpp4
-rw-r--r--src/particles/qquickimageparticle.cpp4
-rw-r--r--src/particles/qquickimageparticle_p.h4
-rw-r--r--src/particles/qquickparticleemitter_p.h2
-rw-r--r--src/particles/qquickparticlesystem.cpp1
-rw-r--r--src/particles/qquickpointattractor_p.h4
-rw-r--r--src/particles/qquicktrailemitter_p.h2
-rw-r--r--src/particles/qquickv4particledata_p.h2
-rw-r--r--src/particles/qquickwander_p.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp188
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.h (renamed from src/qml/qml/qqmlabstractexpression.cpp)79
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qmldbg_local.pri14
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro8
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp1
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp7
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h1
-rw-r--r--src/plugins/qmltooling/qmltooling.pro2
-rw-r--r--src/plugins/qmltooling/shared/abstractviewinspector.cpp1
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp2
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp10
-rw-r--r--src/qml/compiler/qv4codegen.cpp3
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4compiler.cpp7
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp4
-rw-r--r--src/qml/compiler/qv4isel_p.cpp2
-rw-r--r--src/qml/debugger/qqmldebug.h1
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp166
-rw-r--r--src/qml/debugger/qqmldebugserver_p.h1
-rw-r--r--src/qml/debugger/qqmldebugserverconnection_p.h1
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h2
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp24
-rw-r--r--src/qml/debugger/qqmlinspectorservice.cpp10
-rw-r--r--src/qml/debugger/qv4debugservice.cpp19
-rw-r--r--src/qml/jit/qv4assembler.cpp20
-rw-r--r--src/qml/jit/qv4assembler_p.h12
-rw-r--r--src/qml/jit/qv4binop.cpp63
-rw-r--r--src/qml/jit/qv4isel_masm.cpp13
-rw-r--r--src/qml/jit/qv4regalloc.cpp2
-rw-r--r--src/qml/jit/qv4targetplatform_p.h65
-rw-r--r--src/qml/jsapi/qjsengine.cpp11
-rw-r--r--src/qml/jsapi/qjsvalue.cpp33
-rw-r--r--src/qml/jsapi/qjsvalue_p.h2
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp39
-rw-r--r--src/qml/jsapi/qjsvalueiterator_p.h10
-rw-r--r--src/qml/jsruntime/jsruntime.pri6
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp35
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp19
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h4
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp61
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h4
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4context.cpp320
-rw-r--r--src/qml/jsruntime/qv4context_p.h40
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp15
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h6
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp174
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h23
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp7
-rw-r--r--src/qml/jsruntime/qv4engine.cpp589
-rw-r--r--src/qml/jsruntime/qv4engine_p.h303
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp69
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h22
-rw-r--r--src/qml/jsruntime/qv4function.cpp4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp125
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h59
-rw-r--r--src/qml/jsruntime/qv4global_p.h5
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp15
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4include.cpp12
-rw-r--r--src/qml/jsruntime/qv4include_p.h2
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h2
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp152
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h52
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp69
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h20
-rw-r--r--src/qml/jsruntime/qv4managed.cpp4
-rw-r--r--src/qml/jsruntime/qv4managed_p.h101
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp3
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp17
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp137
-rw-r--r--src/qml/jsruntime/qv4object_p.h87
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp25
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h4
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp72
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h4
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp10
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h20
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp3
-rw-r--r--src/qml/jsruntime/qv4property_p.h9
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp137
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h24
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp25
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h3
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp42
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp103
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h7
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h55
-rw-r--r--src/qml/jsruntime/qv4script.cpp84
-rw-r--r--src/qml/jsruntime/qv4script_p.h18
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp26
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h5
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp22
-rw-r--r--src/qml/jsruntime/qv4serialize_p.h2
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h12
-rw-r--r--src/qml/jsruntime/qv4string.cpp2
-rw-r--r--src/qml/jsruntime/qv4string_p.h14
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp82
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h18
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp29
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h8
-rw-r--r--src/qml/jsruntime/qv4value.cpp64
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h293
-rw-r--r--src/qml/jsruntime/qv4value_p.h246
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp5
-rw-r--r--src/qml/memory/memory.pri14
-rw-r--r--src/qml/memory/qv4heap_p.h128
-rw-r--r--src/qml/memory/qv4mm.cpp (renamed from src/qml/jsruntime/qv4mm.cpp)6
-rw-r--r--src/qml/memory/qv4mm_p.h (renamed from src/qml/jsruntime/qv4mm_p.h)6
-rw-r--r--src/qml/qml.pro4
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h25
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp27
-rw-r--r--src/qml/qml/ftw/qqmlthread_p.h2
-rw-r--r--src/qml/qml/qml.pri2
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp170
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h140
-rw-r--r--src/qml/qml/qqmlabstractexpression_p.h116
-rw-r--r--src/qml/qml/qqmlbinding.cpp433
-rw-r--r--src/qml/qml/qqmlbinding_p.h65
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp308
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h78
-rw-r--r--src/qml/qml/qqmlcomponent.cpp24
-rw-r--r--src/qml/qml/qqmlcomponent.h5
-rw-r--r--src/qml/qml/qqmlcontext.cpp11
-rw-r--r--src/qml/qml/qqmlcontext.h1
-rw-r--r--src/qml/qml/qqmlcontext_p.h6
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp94
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h29
-rw-r--r--src/qml/qml/qqmldata_p.h17
-rw-r--r--src/qml/qml/qqmldirparser.cpp4
-rw-r--r--src/qml/qml/qqmlengine.cpp105
-rw-r--r--src/qml/qml/qqmlengine.h4
-rw-r--r--src/qml/qml/qqmlengine_p.h33
-rw-r--r--src/qml/qml/qqmlexpression.cpp34
-rw-r--r--src/qml/qml/qqmlexpression_p.h12
-rw-r--r--src/qml/qml/qqmlimport.cpp25
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp120
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h99
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp10
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h6
-rw-r--r--src/qml/qml/qqmllocale.cpp32
-rw-r--r--src/qml/qml/qqmllocale_p.h10
-rw-r--r--src/qml/qml/qqmlmemoryprofiler.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp15
-rw-r--r--src/qml/qml/qqmlnotifier_p.h12
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp57
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp12
-rw-r--r--src/qml/qml/qqmlproperty.cpp455
-rw-r--r--src/qml/qml/qqmlproperty_p.h38
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp5
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp23
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp10
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp4
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding.cpp97
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h20
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp79
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp17
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp69
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp42
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h6
-rw-r--r--src/qml/qml/v8/qv4domerrors.cpp2
-rw-r--r--src/qml/qml/v8/qv4sqlerrors.cpp2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp23
-rw-r--r--src/qml/qml/v8/qv8engine_p.h14
-rw-r--r--src/qml/types/qqmlbind.cpp21
-rw-r--r--src/qml/types/qqmlconnections.cpp2
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp35
-rw-r--r--src/qml/types/qqmllistmodel.cpp30
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp1
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp204
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h11
-rw-r--r--src/qml/types/qquickworkerscript.cpp2
-rw-r--r--src/qml/util/qqmladaptormodel.cpp6
-rw-r--r--src/qmldevtools/qmldevtools.pro1
-rw-r--r--src/qmltest/qmltest.pro4
-rw-r--r--src/qmltest/quicktest.h11
-rw-r--r--src/qmltest/quicktestresult.cpp21
-rw-r--r--src/qmltest/quicktestresult_p.h2
-rw-r--r--src/quick/designer/designersupport.cpp9
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp4
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h4
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp24
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h2
-rw-r--r--src/quick/items/qquickanchors.cpp28
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h2
-rw-r--r--src/quick/items/qquickborderimage_p.h2
-rw-r--r--src/quick/items/qquickdrag_p.h3
-rw-r--r--src/quick/items/qquickflickable.cpp3
-rw-r--r--src/quick/items/qquickflickable_p.h2
-rw-r--r--src/quick/items/qquickflipable_p.h2
-rw-r--r--src/quick/items/qquickframebufferobject.cpp31
-rw-r--r--src/quick/items/qquickframebufferobject.h5
-rw-r--r--src/quick/items/qquickgridview.cpp10
-rw-r--r--src/quick/items/qquickgridview_p.h4
-rw-r--r--src/quick/items/qquickimage_p.h8
-rw-r--r--src/quick/items/qquickimagebase.cpp30
-rw-r--r--src/quick/items/qquickimagebase_p.h2
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p_p.h2
-rw-r--r--src/quick/items/qquickitem.cpp8
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h6
-rw-r--r--src/quick/items/qquickitemanimation_p.h2
-rw-r--r--src/quick/items/qquickitemsmodule.cpp18
-rw-r--r--src/quick/items/qquickitemview.cpp67
-rw-r--r--src/quick/items/qquickitemview_p.h9
-rw-r--r--src/quick/items/qquickitemview_p_p.h4
-rw-r--r--src/quick/items/qquickitemviewtransition.cpp1
-rw-r--r--src/quick/items/qquickitemviewtransition_p.h12
-rw-r--r--src/quick/items/qquicklistview.cpp59
-rw-r--r--src/quick/items/qquicklistview_p.h12
-rw-r--r--src/quick/items/qquickloader.cpp2
-rw-r--r--src/quick/items/qquickloader_p.h2
-rw-r--r--src/quick/items/qquickloader_p_p.h2
-rw-r--r--src/quick/items/qquickopenglinfo_p.h3
-rw-r--r--src/quick/items/qquickpainteditem.h2
-rw-r--r--src/quick/items/qquickpainteditem_p.h2
-rw-r--r--src/quick/items/qquickpathview.cpp159
-rw-r--r--src/quick/items/qquickpathview_p.h7
-rw-r--r--src/quick/items/qquickpathview_p_p.h1
-rw-r--r--src/quick/items/qquickpincharea_p.h2
-rw-r--r--src/quick/items/qquickpositioners.cpp319
-rw-r--r--src/quick/items/qquickpositioners_p.h46
-rw-r--r--src/quick/items/qquickpositioners_p_p.h23
-rw-r--r--src/quick/items/qquickrepeater.cpp21
-rw-r--r--src/quick/items/qquickscalegrid_p_p.h1
-rw-r--r--src/quick/items/qquickshadereffect_p.h4
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp4
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h3
-rw-r--r--src/quick/items/qquickstateoperations.cpp201
-rw-r--r--src/quick/items/qquickstateoperations_p.h8
-rw-r--r--src/quick/items/qquicktext.cpp274
-rw-r--r--src/quick/items/qquicktext_p.h49
-rw-r--r--src/quick/items/qquicktext_p_p.h20
-rw-r--r--src/quick/items/qquicktextcontrol.cpp4
-rw-r--r--src/quick/items/qquicktextedit.cpp269
-rw-r--r--src/quick/items/qquicktextedit_p.h47
-rw-r--r--src/quick/items/qquicktextedit_p_p.h31
-rw-r--r--src/quick/items/qquicktextinput.cpp437
-rw-r--r--src/quick/items/qquicktextinput_p.h85
-rw-r--r--src/quick/items/qquicktextinput_p_p.h24
-rw-r--r--src/quick/items/qquicktextnode.cpp45
-rw-r--r--src/quick/items/qquicktextnode_p.h4
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp2
-rw-r--r--src/quick/items/qquicktextnodeengine_p.h2
-rw-r--r--src/quick/items/qquickview.cpp18
-rw-r--r--src/quick/items/qquickview.h3
-rw-r--r--src/quick/items/qquickwindow.cpp122
-rw-r--r--src/quick/items/qquickwindow.h8
-rw-r--r--src/quick/items/qquickwindow_p.h2
-rw-r--r--src/quick/qtquick2.cpp1
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp37
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h18
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp4
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp68
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h10
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp11
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp6
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp11
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp16
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h2
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp655
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h124
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp59
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h1
-rw-r--r--src/quick/scenegraph/scenegraph.pri2
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture_p.h3
-rw-r--r--src/quick/scenegraph/util/qsgengine.cpp15
-rw-r--r--src/quick/scenegraph/util/qsgengine.h3
-rw-r--r--src/quick/util/qquickanimation_p.h4
-rw-r--r--src/quick/util/qquickanimation_p_p.h2
-rw-r--r--src/quick/util/qquickanimator_p.h3
-rw-r--r--src/quick/util/qquickanimatorjob.cpp5
-rw-r--r--src/quick/util/qquickanimatorjob_p.h1
-rw-r--r--src/quick/util/qquickfontloader_p.h2
-rw-r--r--src/quick/util/qquickimageprovider.cpp125
-rw-r--r--src/quick/util/qquickimageprovider.h32
-rw-r--r--src/quick/util/qquickpath_p.h2
-rw-r--r--src/quick/util/qquickpixmapcache.cpp240
-rw-r--r--src/quick/util/qquickpropertychanges.cpp32
-rw-r--r--src/quick/util/qquicksmoothedanimation_p.h2
-rw-r--r--src/quick/util/qquickstate.cpp49
-rw-r--r--src/quick/util/qquickstate_p.h12
-rw-r--r--src/quick/util/qquickstate_p_p.h10
-rw-r--r--src/quick/util/qquickstatechangescript.cpp2
-rw-r--r--src/quick/util/qquickstatechangescript_p.h2
-rw-r--r--src/quick/util/qquickstyledtext.cpp4
-rw-r--r--src/quick/util/qquicksystempalette_p.h2
-rw-r--r--src/quick/util/qquicktimeline.cpp2
-rw-r--r--src/quick/util/qquicktransitionmanager.cpp28
-rw-r--r--src/quick/util/qquickutilmodule.cpp8
-rw-r--r--src/quick/util/qquickvalidator.cpp221
-rw-r--r--src/quick/util/qquickvalidator_p.h83
-rw-r--r--src/quick/util/qquickvaluetypes_p.h4
-rw-r--r--src/quick/util/util.pri6
-rw-r--r--src/quickwidgets/qquickwidget.cpp18
-rw-r--r--src/quickwidgets/qquickwidget.h3
-rw-r--r--sync.profile2
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/BLACKLIST2
-rw-r--r--tests/auto/qml/debugger/debugger.pro1
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp3
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/qqmldebuglocal.pro16
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp161
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.pro0
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp4
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugclient.cpp61
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugclient.h1
-rw-r--r--tests/auto/qml/qml.pro4
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp30
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlobjectmodel/qqmlobjectmodel.pro10
-rw-r--r--tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp134
-rw-r--r--tests/auto/qml/qqmlopenmetaobject/qqmlopenmetaobject.pro9
-rw-r--r--tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp (renamed from src/qml/jsruntime/qv4qmlextensions_p.h)47
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp164
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/cdata.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/json.data6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml22
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect7
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/text.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp21
-rw-r--r--tests/auto/qml/qv4debugger/tst_qv4debugger.cpp4
-rw-r--r--tests/auto/qmldevtools/compile/tst_compile.cpp1
-rw-r--r--tests/auto/qmltest/BLACKLIST5
-rw-r--r--tests/auto/qmltest/objectmodel/tst_objectmodel.qml100
-rw-r--r--tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml71
-rw-r--r--tests/auto/qmltest/selftests/tst_grabImage.qml (renamed from src/qml/jsruntime/qv4qmlextensions.cpp)31
-rw-r--r--tests/auto/qmltest/selftests/tst_selftests.qml26
-rw-r--r--tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml89
-rw-r--r--tests/auto/quick/nokeywords/tst_nokeywords.cpp1
-rw-r--r--tests/auto/quick/qquickbehaviors/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp192
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp7
-rw-r--r--tests/auto/quick/qquickflickable/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp100
-rw-r--r--tests/auto/quick/qquickgridview/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml47
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp82
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp17
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp98
-rw-r--r--tests/auto/quick/qquickitem/BLACKLIST2
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST4
-rw-r--r--tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml46
-rw-r--r--tests/auto/quick/qquicklistview/data/objectmodel.qml24
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp133
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickpathview/data/customAttribute.qml58
-rw-r--r--tests/auto/quick/qquickpathview/data/qtbug42716.qml111
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp57
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp2
-rw-r--r--tests/auto/quick/qquickpositioners/data/allInvisible.qml40
-rw-r--r--tests/auto/quick/qquickpositioners/data/flowtest-padding.qml44
-rw-r--r--tests/auto/quick/qquickpositioners/data/gridtest-padding.qml47
-rw-r--r--tests/auto/quick/qquickpositioners/data/horizontal-padding.qml30
-rw-r--r--tests/auto/quick/qquickpositioners/data/repeatertest-padding.qml53
-rw-r--r--tests/auto/quick/qquickpositioners/data/repeatertest.qml18
-rw-r--r--tests/auto/quick/qquickpositioners/data/transitions-padding.qml239
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp2000
-rw-r--r--tests/auto/quick/qquickrepeater/data/objectmodel.qml28
-rw-r--r--tests/auto/quick/qquickrepeater/data/stackingorder.qml38
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp79
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp8
-rw-r--r--tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp4
-rw-r--r--tests/auto/quick/qquicktext/BLACKLIST4
-rw-r--r--tests/auto/quick/qquicktext/data/padding.qml12
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp208
-rw-r--r--tests/auto/quick/qquicktextedit/BLACKLIST2
-rw-r--r--tests/auto/quick/qquicktextedit/data/padding.qml12
-rw-r--r--tests/auto/quick/qquicktextedit/data/signal_editingfinished.qml13
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp129
-rw-r--r--tests/auto/quick/qquicktextinput/data/padding.qml12
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp181
-rw-r--r--tests/auto/quick/qquickview/data/error2.qml4
-rw-r--r--tests/auto/quick/qquickview/tst_qquickview.cpp9
-rw-r--r--tests/auto/quick/qquickwindow/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp122
-rw-r--r--tests/auto/quick/quick.pro4
-rw-r--r--tests/auto/quick/scenegraph/data/mipmap_large.pngbin4465 -> 6536 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/mipmap_small.pngbin170 -> 124 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/render_Mipmap.qml9
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp103
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp16
-rw-r--r--tests/auto/quick/shared/viewtestutil.h2
-rw-r--r--tests/benchmarks/script/qjsvalue/tst_qjsvalue.cpp77
-rw-r--r--tools/qml/main.cpp37
-rw-r--r--tools/qmleasing/splineeditor.cpp5
-rw-r--r--tools/qmlimportscanner/main.cpp2
-rw-r--r--tools/qmljs/qmljs.cpp14
-rw-r--r--tools/qmllint/main.cpp2
-rw-r--r--tools/qmlplugindump/main.cpp4
-rw-r--r--tools/qmlprofiler/commandlistener.cpp21
-rw-r--r--tools/qmlprofiler/commandlistener.h13
-rw-r--r--tools/qmlprofiler/constants.h19
-rw-r--r--tools/qmlprofiler/main.cpp32
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.cpp528
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.h35
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.cpp102
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.h15
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.cpp70
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.h1
455 files changed, 13756 insertions, 7001 deletions
diff --git a/.gitmodules b/.gitmodules
index 9f78879479..881629497e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +1,4 @@
[submodule "tests/manual/v4/test262"]
path = tests/manual/v4/test262
- url = git://github.com/tronical/test262.git
+ url = ../qtdeclarative-testsuites.git
update = none
diff --git a/.qmake.conf b/.qmake.conf
index 58db72c7b1..fc13c75da5 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
-MODULE_VERSION = 5.5.1
+MODULE_VERSION = 5.6.0
diff --git a/examples/quick/imageresponseprovider/ImageResponseProviderCore/qmldir b/examples/quick/imageresponseprovider/ImageResponseProviderCore/qmldir
new file mode 100644
index 0000000000..3a5821bdf2
--- /dev/null
+++ b/examples/quick/imageresponseprovider/ImageResponseProviderCore/qmldir
@@ -0,0 +1,2 @@
+plugin qmlimageresponseproviderplugin
+
diff --git a/examples/quick/imageresponseprovider/doc/src/imageresponseprovider.qdoc b/examples/quick/imageresponseprovider/doc/src/imageresponseprovider.qdoc
new file mode 100644
index 0000000000..afe1d406d8
--- /dev/null
+++ b/examples/quick/imageresponseprovider/doc/src/imageresponseprovider.qdoc
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Canonical Limited and/or its subsidiary(-ies)
+** Contact: http://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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \title C++ Extensions: Image Response Provider Example
+ \example imageresponseprovider
+
+ This examples shows how to use QQuickImageProvider to serve images
+ asynchronously to QML image elements.
+*/
+
diff --git a/examples/quick/imageresponseprovider/imageresponseprovider-example.qml b/examples/quick/imageresponseprovider/imageresponseprovider-example.qml
new file mode 100644
index 0000000000..20c1e69434
--- /dev/null
+++ b/examples/quick/imageresponseprovider/imageresponseprovider-example.qml
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Canonical Limited and/or its subsidiary(-ies)
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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
+import "ImageResponseProviderCore"
+
+Column {
+ Image { source: "image://async/slow" }
+ Image { source: "image://async/fast" }
+}
+
diff --git a/examples/quick/imageresponseprovider/imageresponseprovider.cpp b/examples/quick/imageresponseprovider/imageresponseprovider.cpp
new file mode 100644
index 0000000000..bdec29114b
--- /dev/null
+++ b/examples/quick/imageresponseprovider/imageresponseprovider.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Canonical Limited and/or its subsidiary(-ies)
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 <qqmlextensionplugin.h>
+
+#include <qqmlengine.h>
+#include <qquickimageprovider.h>
+#include <QDebug>
+#include <QImage>
+#include <QThreadPool>
+
+class AsyncImageResponse : public QQuickImageResponse, public QRunnable
+{
+ public:
+ AsyncImageResponse(const QString &id, const QSize &requestedSize)
+ : m_id(id), m_requestedSize(requestedSize), m_texture(0)
+ {
+ setAutoDelete(false);
+ }
+
+ QQuickTextureFactory *textureFactory() const
+ {
+ return m_texture;
+ }
+
+ void run()
+ {
+ QImage image(50, 50, QImage::Format_RGB32);
+ if (m_id == "slow") {
+ qDebug() << "Slow, red, sleeping for 5 seconds";
+ QThread::sleep(5);
+ image.fill(Qt::red);
+ } else {
+ qDebug() << "Fast, blue, sleeping for 1 second";
+ QThread::sleep(1);
+ image.fill(Qt::blue);
+ }
+ if (m_requestedSize.isValid())
+ image = image.scaled(m_requestedSize);
+ m_texture = QQuickTextureFactory::textureFactoryForImage(image);
+ emit finished();
+ }
+
+ QString m_id;
+ QSize m_requestedSize;
+ QQuickTextureFactory *m_texture;
+};
+
+class AsyncImageProvider : public QQuickAsyncImageProvider
+{
+public:
+ QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize)
+ {
+ AsyncImageResponse *response = new AsyncImageResponse(id, requestedSize);
+ pool.start(response);
+ return response;
+ }
+
+private:
+ QThreadPool pool;
+};
+
+
+class ImageProviderExtensionPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+public:
+ void registerTypes(const char *uri)
+ {
+ Q_UNUSED(uri);
+ }
+
+ void initializeEngine(QQmlEngine *engine, const char *uri)
+ {
+ Q_UNUSED(uri);
+ engine->addImageProvider("async", new AsyncImageProvider);
+ }
+
+};
+
+
+#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
+
+#include "imageresponseprovider.moc"
diff --git a/examples/quick/imageresponseprovider/imageresponseprovider.pro b/examples/quick/imageresponseprovider/imageresponseprovider.pro
new file mode 100644
index 0000000000..856ddde863
--- /dev/null
+++ b/examples/quick/imageresponseprovider/imageresponseprovider.pro
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+CONFIG += plugin
+QT += qml quick
+
+DESTDIR = ImageResponseProviderCore
+TARGET = qmlimageresponseproviderplugin
+
+SOURCES += imageresponseprovider.cpp
+
+EXAMPLE_FILES = imageresponseprovider-example.qml
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/imageresponseprovider/ImageResponseProviderCore
+qml.files = ImageResponseProviderCore/qmldir
+qml.path = $$[QT_INSTALL_EXAMPLES]/quick/imageresponseprovider/ImageResponseProviderCore
+INSTALLS = target qml
diff --git a/examples/quick/imageresponseprovider/imageresponseprovider.qmlproject b/examples/quick/imageresponseprovider/imageresponseprovider.qmlproject
new file mode 100644
index 0000000000..2bb4016996
--- /dev/null
+++ b/examples/quick/imageresponseprovider/imageresponseprovider.qmlproject
@@ -0,0 +1,14 @@
+import QmlProject 1.0
+
+Project {
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+}
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index a412c53a65..c5ef46173c 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -20,6 +20,7 @@ SUBDIRS = quick-accessibility \
tutorials \
customitems \
imageprovider \
+ imageresponseprovider \
window \
particles \
demos \
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.cpp b/examples/quick/scenegraph/openglunderqml/squircle.cpp
index 8ef975c5b6..2834b93e10 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.cpp
+++ b/examples/quick/scenegraph/openglunderqml/squircle.cpp
@@ -97,6 +97,7 @@ void Squircle::sync()
}
m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
m_renderer->setT(m_t);
+ m_renderer->setWindow(window());
}
//! [9]
@@ -156,5 +157,9 @@ void SquircleRenderer::paint()
m_program->disableAttributeArray(0);
m_program->release();
+
+ // Not strictly needed for this example, but generally useful for when
+ // mixing with raw OpenGL.
+ m_window->resetOpenGLState();
}
//! [5]
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.h b/examples/quick/scenegraph/openglunderqml/squircle.h
index f797d7a7a5..28016def44 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.h
+++ b/examples/quick/scenegraph/openglunderqml/squircle.h
@@ -50,6 +50,7 @@ public:
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 paint();
@@ -58,6 +59,7 @@ private:
QSize m_viewportSize;
qreal m_t;
QOpenGLShaderProgram *m_program;
+ QQuickWindow *m_window;
};
//! [1]
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
index 03f8e2d71a..734e779c70 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
@@ -359,6 +359,12 @@ public:
}
}
+ void mul32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ mul32(dataTempRegister, dest);
+ }
+
void neg32(RegisterID srcDest)
{
m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
@@ -420,6 +426,12 @@ public:
store32(dataTempRegister, dest.m_ptr);
}
+ void or32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ or32(dataTempRegister, dest);
+ }
+
void rshift32(RegisterID shiftAmount, RegisterID dest)
{
m_assembler.srav(dest, dest, shiftAmount);
@@ -615,6 +627,12 @@ public:
m_assembler.xorInsn(dest, src, immTempRegister);
}
+ void xor32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ xor32(dataTempRegister, dest);
+ }
+
void sqrtDouble(FPRegisterID src, FPRegisterID dst)
{
m_assembler.sqrtd(dst, src);
@@ -2519,6 +2537,18 @@ public:
m_assembler.cvtdw(dest, fpTempRegister);
}
+ void convertUInt32ToDouble(RegisterID src, FPRegisterID dest, RegisterID scratch)
+ {
+ m_assembler.mtc1(src, fpTempRegister);
+ m_assembler.bltz(src, 2);
+ m_assembler.cvtdw(dest, fpTempRegister);
+ m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 4);
+ m_assembler.lui(scratch, 0x4f80);
+ m_assembler.mtc1(scratch, fpTempRegister);
+ m_assembler.cvtds(fpTempRegister, fpTempRegister);
+ m_assembler.addd(dest, dest, fpTempRegister);
+ }
+
void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
{
m_assembler.cvtds(dst, src);
@@ -2761,7 +2791,7 @@ public:
return CodeLocationLabel();
}
- static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue)
+ static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*)
{
UNREACHABLE_FOR_PLATFORM();
}
diff --git a/src/3rdparty/masm/disassembler/Mips32Disassembler.cpp b/src/3rdparty/masm/disassembler/Mips32Disassembler.cpp
new file mode 100644
index 0000000000..af0a73b2cb
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/Mips32Disassembler.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS, INC. ``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 CISCO SYSTEMS, INC. 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.
+ */
+
+#include "config.h"
+#include "Disassembler.h"
+
+#if USE(MIPS32_DISASSEMBLER)
+
+#include "mips32/Mips32Opcode.h"
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out)
+{
+ Mips32Opcode mipsOpcode;
+
+ uint32_t* currentPC = reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(codePtr.executableAddress()) & ~3);
+ uint32_t* endPC = currentPC + (size / sizeof(uint32_t));
+
+ while (currentPC < endPC) {
+ char pcString[12];
+ snprintf(pcString, sizeof(pcString), "0x%x", reinterpret_cast<unsigned>(currentPC));
+ out.printf("%s%10s: %s\n", prefix, pcString, mipsOpcode.disassemble(currentPC));
+ currentPC++;
+ }
+
+ return true;
+}
+
+} // namespace JSC
+
+#endif // USE(MIPS32_DISASSEMBLER)
+
diff --git a/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp
new file mode 100644
index 0000000000..164217eb55
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS, INC. ``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 CISCO SYSTEMS, INC. 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.
+ */
+
+#include "config.h"
+
+#if USE(MIPS32_DISASSEMBLER)
+
+#include "Mips32Opcode.h"
+
+#include <stdio.h>
+
+#define OPCODE_FMT "%s\t"
+#define COP1_OPCODE_FMT "%s.%s\t"
+#define FORMAT_INSTR(_format, ...) \
+ snprintf(m_formatBuffer, bufferSize - 1, _format, ##__VA_ARGS__)
+
+const char *Mips32Opcode::registerName(uint8_t r)
+{
+ static const char *gpRegisters[] = {
+ "zero", "AT", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "kt0", "kt1", "gp", "sp", "s8", "ra"
+ };
+
+ return (r < sizeof(gpRegisters)) ? gpRegisters[r] : "invalid";
+}
+
+const char *Mips32Opcode::fpRegisterName(uint8_t r)
+{
+ static const char *fpRegisters[] = {
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
+ };
+
+ return (r < sizeof(fpRegisters)) ? fpRegisters[r] : "invalid";
+}
+
+void Mips32Opcode::formatSpecialEncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t shift, uint8_t function)
+{
+ const char *opcode;
+ OpcodePrintFormat format = Unknown;
+ switch (function) {
+ case 0x00:
+ format = RdRtSa;
+ opcode = "sll";
+ break;
+ case 0x02:
+ format = RdRtSa;
+ opcode = "srl";
+ break;
+ case 0x03:
+ format = RdRtSa;
+ opcode = "sra";
+ break;
+ case 0x04:
+ format = RdRtRs;
+ opcode = "sllv";
+ break;
+ case 0x06:
+ format = RdRtRs;
+ opcode = "srlv";
+ break;
+ case 0x07:
+ format = RdRtRs;
+ opcode = "srav";
+ break;
+ case 0x08:
+ format = Rs;
+ opcode = "jr";
+ break;
+ case 0x09:
+ format = (dest != 0x1f) ? RdRs : Rs;
+ opcode = "jalr";
+ break;
+ case 0x10:
+ format = Rd;
+ opcode = "mfhi";
+ break;
+ case 0x11:
+ format = Rs;
+ opcode = "mthi";
+ break;
+ case 0x12:
+ format = Rd;
+ opcode = "mflo";
+ break;
+ case 0x13:
+ format = Rs;
+ opcode = "mtlo";
+ break;
+ case 0x18:
+ format = RsRt;
+ opcode = "mult";
+ break;
+ case 0x19:
+ format = RsRt;
+ opcode = "multu";
+ break;
+ case 0x1a:
+ format = RsRt;
+ opcode = "div";
+ break;
+ case 0x1b:
+ format = RsRt;
+ opcode = "divu";
+ break;
+ case 0x20:
+ format = RdRsRt;
+ opcode = "add";
+ break;
+ case 0x21:
+ if (op2) {
+ format = RdRsRt;
+ opcode = "addu";
+ } else {
+ format = RdRs;
+ opcode = "move";
+ }
+ break;
+ case 0x22:
+ format = RdRsRt;
+ opcode = "sub";
+ break;
+ case 0x23:
+ format = RdRsRt;
+ opcode = "subu";
+ break;
+ case 0x24:
+ format = RdRsRt;
+ opcode = "and";
+ break;
+ case 0x25:
+ format = RdRsRt;
+ opcode = "or";
+ break;
+ case 0x26:
+ format = RdRsRt;
+ opcode = "xor";
+ break;
+ case 0x27:
+ format = RdRsRt;
+ opcode = "nor";
+ break;
+ case 0x2a:
+ format = RdRsRt;
+ opcode = "slt";
+ break;
+ case 0x2b:
+ format = RdRsRt;
+ opcode = "sltu";
+ break;
+ }
+
+ switch (format) {
+ case Rs:
+ FORMAT_INSTR(OPCODE_FMT "%s", opcode, registerName(op1));
+ break;
+ case Rd:
+ FORMAT_INSTR(OPCODE_FMT "%s", opcode, registerName(dest));
+ break;
+ case RdRs:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s", opcode, registerName(dest), registerName(op1));
+ break;
+ case RsRt:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s", opcode, registerName(op1), registerName(op2));
+ break;
+ case RdRtRs:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %s", opcode, registerName(dest), registerName(op2), registerName(op1));
+ break;
+ case RdRsRt:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %s", opcode, registerName(dest), registerName(op1), registerName(op2));
+ break;
+ case RdRtSa:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %d", opcode, registerName(dest), registerName(op2), shift);
+ break;
+ default:
+ FORMAT_INSTR("unknown special encoding opcode 0x%x", function);
+ break;
+ }
+}
+
+void Mips32Opcode::formatSpecial2EncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t function)
+{
+ if (function == 0x02) {
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %s", "mul", registerName(dest), registerName(op1), registerName(op2));
+ return;
+ }
+
+ FORMAT_INSTR("unknown special2 encoding opcode 0x%x", function);
+}
+
+void Mips32Opcode::formatJumpEncodingOpcode(uint32_t iOp, uint32_t index, uint32_t* opcodePtr)
+{
+ if ((iOp != 0x02) && (iOp != 0x03)) {
+ FORMAT_INSTR("unknown jump encoding opcode 0x%x", iOp);
+ return;
+ }
+
+ FORMAT_INSTR(OPCODE_FMT "0x%x", (iOp == 0x02) ? "j" : "jal",
+ (reinterpret_cast<unsigned>(opcodePtr+1) & 0xf0000000) | (index << 2));
+}
+
+void Mips32Opcode::formatREGIMMEncodingOpcode(uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr)
+{
+ const char *opcodes[] = { "bltz", "bgez", "bltzl", "bgezl" };
+ if (rt < sizeof(opcodes))
+ FORMAT_INSTR(OPCODE_FMT "%s, 0x%x", opcodes[rt], registerName(rs), reinterpret_cast<unsigned>(opcodePtr+1) + (imm << 2));
+ else
+ FORMAT_INSTR("unknown REGIMM encoding opcode 0x%x", rt);
+}
+
+void Mips32Opcode::formatImmediateEncodingOpcode(uint32_t iOp, uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr)
+{
+ const char *opcode;
+ OpcodePrintFormat format = Unknown;
+ switch (iOp) {
+ case 0x04:
+ if (!rs && !rt) {
+ format = Addr;
+ opcode = "b";
+ } else {
+ format = RsRtAddr;
+ opcode = "beq";
+ }
+ break;
+ case 0x05:
+ format = RsRtAddr;
+ opcode = "bne";
+ break;
+ case 0x06:
+ format = RsRtAddr;
+ opcode = "blez";
+ break;
+ case 0x07:
+ format = RsRtAddr;
+ opcode = "bgtz";
+ break;
+ case 0x08:
+ format = RtRsImm;
+ opcode = "addi";
+ break;
+ case 0x09:
+ if (rs) {
+ format = RtRsImm;
+ opcode = "addiu";
+ } else {
+ format = RtUImm;
+ opcode = "li";
+ }
+ break;
+ case 0x0a:
+ format = RtRsImm;
+ opcode = "slti";
+ break;
+ case 0x0b:
+ format = RtRsImm;
+ opcode = "sltiu";
+ break;
+ case 0x0c:
+ format = RtRsImm;
+ opcode = "andi";
+ break;
+ case 0x0d:
+ format = RtRsImm;
+ opcode = "ori";
+ break;
+ case 0x0e:
+ format = RtRsImm;
+ opcode = "xori";
+ break;
+ case 0x0f:
+ format = RtUImm;
+ opcode = "lui";
+ break;
+ case 0x20:
+ format = RtOffsetBase;
+ opcode = "lb";
+ break;
+ case 0x21:
+ format = RtOffsetBase;
+ opcode = "lh";
+ break;
+ case 0x22:
+ format = RtOffsetBase;
+ opcode = "lwl";
+ break;
+ case 0x23:
+ format = RtOffsetBase;
+ opcode = "lw";
+ break;
+ case 0x24:
+ format = RtOffsetBase;
+ opcode = "lbu";
+ break;
+ case 0x25:
+ format = RtOffsetBase;
+ opcode = "lhu";
+ break;
+ case 0x26:
+ format = RtOffsetBase;
+ opcode = "lwr";
+ break;
+ case 0x28:
+ format = RtOffsetBase;
+ opcode = "sb";
+ break;
+ case 0x29:
+ format = RtOffsetBase;
+ opcode = "sh";
+ break;
+ case 0x2a:
+ format = RtOffsetBase;
+ opcode = "swl";
+ break;
+ case 0x2b:
+ format = RtOffsetBase;
+ opcode = "sw";
+ break;
+ case 0x2e:
+ format = RtOffsetBase;
+ opcode = "swr";
+ break;
+ case 0x35:
+ format = FtOffsetBase;
+ opcode = "ldc1";
+ break;
+ case 0x3d:
+ format = FtOffsetBase;
+ opcode = "sdc1";
+ break;
+ }
+
+ switch (format) {
+ case Addr:
+ FORMAT_INSTR(OPCODE_FMT "0x%x", opcode, reinterpret_cast<unsigned>(opcodePtr+1) + (imm << 2));
+ break;
+ case RtUImm:
+ FORMAT_INSTR(OPCODE_FMT "%s, 0x%hx", opcode, registerName(rt), imm);
+ break;
+ case RtRsImm:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %d", opcode, registerName(rt), registerName(rs), imm);
+ break;
+ case RsRtAddr:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, 0x%x", opcode, registerName(rs), registerName(rt),
+ reinterpret_cast<unsigned>(opcodePtr+1) + (imm << 2));
+ break;
+ case RtOffsetBase:
+ FORMAT_INSTR(OPCODE_FMT "%s, %d(%s)", opcode, registerName(rt), imm, registerName(rs));
+ break;
+ case FtOffsetBase:
+ FORMAT_INSTR(OPCODE_FMT "%s, %d(%s)", opcode, fpRegisterName(rt), imm, registerName(rs));
+ break;
+ default:
+ FORMAT_INSTR("unknown immediate encoding opcode 0x%x", iOp);
+ break;
+ }
+}
+
+void Mips32Opcode::formatCOP1Opcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t fd, uint8_t func)
+{
+ const char *opcode;
+ const char *suffix;
+ OpcodePrintFormat format = Unknown;
+
+ if (fmt < 0x10) {
+ switch (fmt) {
+ case 0x00:
+ opcode = "mfc1";
+ break;
+ case 0x04:
+ opcode = "mtc1";
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 rs 0x%x", fmt);
+ return;
+ }
+ FORMAT_INSTR(OPCODE_FMT "%s, %s", opcode, registerName(ft), fpRegisterName(fs));
+ return;
+ }
+
+ switch (fmt) {
+ case 0x10:
+ suffix = "s";
+ break;
+ case 0x11:
+ suffix = "d";
+ break;
+ case 0x14:
+ suffix = "w";
+ break;
+ case 0x15:
+ suffix = "l";
+ break;
+ case 0x16:
+ suffix = "ps";
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 fmt 0x%x", fmt);
+ return;
+ }
+
+ switch (func) {
+ case 0x00:
+ format = FdFsFt;
+ opcode = "add";
+ break;
+ case 0x01:
+ format = FdFsFt;
+ opcode = "sub";
+ break;
+ case 0x02:
+ format = FdFsFt;
+ opcode = "mul";
+ break;
+ case 0x03:
+ format = FdFsFt;
+ opcode = "div";
+ break;
+ case 0x04:
+ format = FdFs;
+ opcode = "sqrt";
+ break;
+ case 0x05:
+ format = FdFs;
+ opcode = "abs";
+ break;
+ case 0x06:
+ format = FdFs;
+ opcode = "mov";
+ break;
+ case 0x07:
+ format = FdFs;
+ opcode = "neg";
+ break;
+ case 0x08:
+ format = FdFs;
+ opcode = "round.l";
+ break;
+ case 0x09:
+ format = FdFs;
+ opcode = "trunc.l";
+ break;
+ case 0x0a:
+ format = FdFs;
+ opcode = "ceil.l";
+ break;
+ case 0x0b:
+ format = FdFs;
+ opcode = "floor.l";
+ break;
+ case 0x0c:
+ format = FdFs;
+ opcode = "round.w";
+ break;
+ case 0x0d:
+ format = FdFs;
+ opcode = "trunc.w";
+ break;
+ case 0x0e:
+ format = FdFs;
+ opcode = "ceil.w";
+ break;
+ case 0x0f:
+ format = FdFs;
+ opcode = "floor.w";
+ break;
+ case 0x20:
+ format = FdFs;
+ opcode = "cvt.s";
+ break;
+ case 0x21:
+ format = FdFs;
+ opcode = "cvt.d";
+ break;
+ case 0x24:
+ format = FdFs;
+ opcode = "cvt.w";
+ break;
+ case 0x25:
+ format = FdFs;
+ opcode = "cvt.l";
+ break;
+ }
+
+ switch (format) {
+ case FdFs:
+ FORMAT_INSTR(COP1_OPCODE_FMT "%s, %s", opcode, suffix, fpRegisterName(fd), fpRegisterName(fs));
+ break;
+ case FdFsFt:
+ FORMAT_INSTR(COP1_OPCODE_FMT "%s, %s, %s", opcode, suffix, fpRegisterName(fd), fpRegisterName(fs), fpRegisterName(ft));
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 opcode 0x%x", func);
+ break;
+ }
+}
+
+void Mips32Opcode::formatCOP1FPCompareOpcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t cc, uint8_t cond)
+{
+ const char *suffix;
+ static const char *opcodes[] = {
+ "c.f", "c.un", "c.eq", "c.ueq", "c.olt", "c.ult", "c.ole", "c.ule",
+ "c.sf", "c.ngle", "c.seq", "c.ngl", "c.lt", "c.nge", "c.le", "c.ngt"
+ };
+ ASSERT(cond < sizeof(opcdoes));
+
+ switch (fmt) {
+ case 0x10:
+ suffix = "s";
+ break;
+ case 0x11:
+ suffix = "d";
+ break;
+ case 0x16:
+ suffix = "ps";
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 fmt 0x%x", fmt);
+ return;
+ }
+
+ if (!cc)
+ FORMAT_INSTR(COP1_OPCODE_FMT "%s, %s", opcodes[cond], suffix, fpRegisterName(fs), fpRegisterName(ft));
+ else
+ FORMAT_INSTR(COP1_OPCODE_FMT "%d, %s, %s", opcodes[cond], suffix, cc, fpRegisterName(fs), fpRegisterName(ft));
+}
+
+void Mips32Opcode::formatCOP1BCOpcode(uint8_t cc, uint8_t ndtf, int16_t offset, uint32_t* opcodePtr)
+{
+ static const char *opcodes[] = { "bc1f", "bc1t", "bc1fl", "bc1tl" };
+ ASSERT(ndtf < sizeof(opcodes));
+
+ if (!cc)
+ FORMAT_INSTR(OPCODE_FMT "0x%x", opcodes[ndtf], reinterpret_cast<unsigned>(opcodePtr+1) + (offset << 2));
+ else
+ FORMAT_INSTR(OPCODE_FMT "%d, 0x%x", opcodes[ndtf], cc, reinterpret_cast<unsigned>(opcodePtr+1) + (offset << 2));
+}
+
+const char* Mips32Opcode::disassemble(uint32_t* opcodePtr)
+{
+ uint32_t opcode = *opcodePtr;
+ uint32_t iOp = (opcode >> 26) & 0x3f;
+
+ if (!opcode)
+ FORMAT_INSTR(OPCODE_FMT, "nop");
+ else if (!iOp) {
+ uint8_t op1 = (opcode >> 21) & 0x1f;
+ uint8_t op2 = (opcode >> 16) & 0x1f;
+ uint8_t dst = (opcode >> 11) & 0x1f;
+ uint8_t shft = (opcode >> 6) & 0x1f;
+ uint8_t func = opcode & 0x3f;
+ formatSpecialEncodingOpcode(op1, op2, dst, shft, func);
+ } else if ((iOp == 0x02) || (iOp == 0x03)) {
+ uint32_t index = opcode & 0x3ffffff;
+ formatJumpEncodingOpcode(iOp, index, opcodePtr);
+ } else if (iOp == 0x11) {
+ uint8_t fmt = (opcode >> 21) & 0x1f;
+ if (fmt == 0x08) {
+ uint8_t cc = (opcode >> 18) & 0x07;
+ uint8_t ndtf = (opcode >> 16) & 0x03;
+ int16_t offset = opcode & 0xffff;
+ formatCOP1BCOpcode(cc, ndtf, offset, opcodePtr);
+ } else if ((opcode & 0xf0) == 0x30) {
+ uint8_t ft = (opcode >> 16) & 0x1f;
+ uint8_t fs = (opcode >> 11) & 0x1f;
+ uint8_t cc = (opcode >> 8) & 0x07;
+ uint8_t cond = opcode & 0x0f;
+ formatCOP1FPCompareOpcode(fmt, ft, fs, cc, cond);
+ } else {
+ uint8_t ft = (opcode >> 16) & 0x1f;
+ uint8_t fs = (opcode >> 11) & 0x1f;
+ uint8_t fd = (opcode >> 6) & 0x1f;
+ uint8_t func = opcode & 0x3f;
+ formatCOP1Opcode(fmt, ft, fs, fd, func);
+ }
+ } else if (iOp == 0x1c) {
+ uint8_t op1 = (opcode >> 21) & 0x1f;
+ uint8_t op2 = (opcode >> 16) & 0x1f;
+ uint8_t dst = (opcode >> 11) & 0x1f;
+ uint8_t func = opcode & 0x3f;
+ formatSpecial2EncodingOpcode(op1, op2, dst, func);
+ } else {
+ uint8_t rs = (opcode >> 21) & 0x1f;
+ uint8_t rt = (opcode >> 16) & 0x1f;
+ int16_t imm = opcode & 0xffff;
+ if (iOp == 0x01)
+ formatREGIMMEncodingOpcode(rs, rt, imm, opcodePtr);
+ else
+ formatImmediateEncodingOpcode(iOp, rs, rt, imm, opcodePtr);
+ }
+
+ return m_formatBuffer;
+}
+
+#endif // USE(MIPS32_DISASSEMBLER)
diff --git a/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h
new file mode 100644
index 0000000000..c63fb1109a
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS, INC. ``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 CISCO SYSTEMS, INC. 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.
+ */
+
+#ifndef _MIPS32Opcode_h_
+#define _MIPS32Opcode_h_
+
+#if USE(MIPS32_DISASSEMBLER)
+
+#include <stdint.h>
+#include <wtf/Assertions.h>
+
+class Mips32Opcode {
+public:
+ Mips32Opcode() {}
+
+ const char* disassemble(uint32_t*);
+
+private:
+ enum OpcodePrintFormat {
+ Unknown = 0,
+ Rs,
+ Rd,
+ Addr,
+ RdRs,
+ RsRt,
+ RtUImm,
+ RdRtRs,
+ RdRsRt,
+ RdRtSa,
+ RtRsImm,
+ RsRtAddr,
+ RtOffsetBase,
+ FdFs,
+ FdFsFt,
+ FtOffsetBase
+ };
+
+ const char *registerName(uint8_t r);
+ const char *fpRegisterName(uint8_t r);
+ void formatSpecialEncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t shift, uint8_t function);
+ void formatSpecial2EncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t function);
+ void formatJumpEncodingOpcode(uint32_t iOp, uint32_t index, uint32_t* opcodePtr);
+ void formatREGIMMEncodingOpcode(uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr);
+ void formatImmediateEncodingOpcode(uint32_t iOp, uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr);
+ void formatCOP1Opcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t fd, uint8_t func);
+ void formatCOP1FPCompareOpcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t cc, uint8_t cond);
+ void formatCOP1BCOpcode(uint8_t cc, uint8_t ndtf, int16_t offset, uint32_t* opcodePtr);
+
+ static const int bufferSize = 81;
+
+ char m_formatBuffer[bufferSize];
+};
+
+#endif
+
+#endif // _MIPS32Opcode_h_
diff --git a/src/3rdparty/masm/masm-defs.pri b/src/3rdparty/masm/masm-defs.pri
index d0980c5312..f09a8329c9 100644
--- a/src/3rdparty/masm/masm-defs.pri
+++ b/src/3rdparty/masm/masm-defs.pri
@@ -26,6 +26,7 @@ INCLUDEPATH += $$PWD
disassembler {
if(isEqual(QT_ARCH, "i386")|isEqual(QT_ARCH, "x86_64")): DEFINES += WTF_USE_UDIS86=1
if(isEqual(QT_ARCH, "arm")): DEFINES += WTF_USE_ARMV7_DISASSEMBLER=1
+ if(isEqual(QT_ARCH, "mips")): DEFINES += WTF_USE_MIPS32_DISASSEMBLER=1
} else {
DEFINES += WTF_USE_UDIS86=0
}
diff --git a/src/3rdparty/masm/masm.pri b/src/3rdparty/masm/masm.pri
index 3497650f0c..04548fe8a3 100644
--- a/src/3rdparty/masm/masm.pri
+++ b/src/3rdparty/masm/masm.pri
@@ -59,6 +59,9 @@ contains(DEFINES, WTF_USE_UDIS86=1) {
SOURCES += $$PWD/disassembler/ARMv7Disassembler.cpp
SOURCES += $$PWD/disassembler/ARMv7/ARMv7DOpcode.cpp
HEADERS += $$PWD/disassembler/ARMv7/ARMv7DOpcode.h
+SOURCES += $$PWD/disassembler/Mips32Disassembler.cpp
+SOURCES += $$PWD/disassembler/mips32/Mips32Opcode.cpp
+HEADERS += $$PWD/disassembler/mips32/Mips32Opcode.h
SOURCES += $$PWD/yarr/*.cpp
HEADERS += $$PWD/yarr/*.h
diff --git a/src/3rdparty/masm/wtf/Platform.h b/src/3rdparty/masm/wtf/Platform.h
index 3e2a51379c..f0612fe50e 100644
--- a/src/3rdparty/masm/wtf/Platform.h
+++ b/src/3rdparty/masm/wtf/Platform.h
@@ -735,7 +735,7 @@
#define WTF_USE_UDIS86 1
#endif
-#if !defined(ENABLE_DISASSEMBLER) && (USE(UDIS86) || USE(ARMV7_DISASSEMBLER))
+#if !defined(ENABLE_DISASSEMBLER) && (USE(UDIS86) || USE(ARMV7_DISASSEMBLER) || USE(MIPS32_DISASSEMBLER))
#define ENABLE_DISASSEMBLER 1
#endif
diff --git a/src/imports/folderlistmodel/fileinfothread.cpp b/src/imports/folderlistmodel/fileinfothread.cpp
index e1db7834ec..532815e5c1 100644
--- a/src/imports/folderlistmodel/fileinfothread.cpp
+++ b/src/imports/folderlistmodel/fileinfothread.cpp
@@ -251,6 +251,7 @@ void FileInfoThread::getFileInfos(const QString &path)
fileInfoList = currentDir.entryInfoList(nameFilters, filter, sortFlags);
if (!fileInfoList.isEmpty()) {
+ filePropertyList.reserve(fileInfoList.count());
foreach (QFileInfo info, fileInfoList) {
//qDebug() << "Adding file : " << info.fileName() << "to list ";
filePropertyList << FileProperty(info);
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 80b32e64ef..0f4a5bda54 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -788,6 +788,20 @@ QVariant QQuickFolderListModel::get(int idx, const QString &property) const
return QVariant();
}
+/*!
+ \qmlmethod int FolderListModel::indexOf(url file)
+ \since 5.6
+
+ Get the index of the given file URL if the model contains it,
+ or -1 if not.
+*/
+int QQuickFolderListModel::indexOf(const QUrl &file) const
+{
+ Q_D(const QQuickFolderListModel);
+ FileProperty toFind(QFileInfo(file.toLocalFile()));
+ return d->data.indexOf(toFind);
+}
+
#include "moc_qquickfolderlistmodel.cpp"
//![code]
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h
index 63ed528556..fcfec56c87 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.h
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h
@@ -109,9 +109,9 @@ public:
void setNameFilters(const QStringList &filters);
enum SortField { Unsorted, Name, Time, Size, Type };
+ Q_ENUM(SortField)
SortField sortField() const;
void setSortField(SortField field);
- Q_ENUMS(SortField)
bool sortReversed() const;
void setSortReversed(bool rev);
@@ -132,6 +132,7 @@ public:
Q_INVOKABLE bool isFolder(int index) const;
Q_INVOKABLE QVariant get(int idx, const QString &property) const;
+ Q_INVOKABLE int indexOf(const QUrl &file) const;
//![parserstatus]
virtual void classBegin();
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index b0ba3f9228..22a3eed39d 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -126,7 +126,7 @@ public:
~QQmlSqlDatabaseWrapper() {
}
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
}
@@ -214,7 +214,7 @@ static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV4::E
return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName;
}
-static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0)
+static ReturnedValue qmlsqldatabase_rows_index(const QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0)
{
Scope scope(v4);
@@ -238,15 +238,14 @@ static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, Execut
}
}
-ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- QV4::Scope scope(static_cast<QQmlSqlDatabaseWrapper *>(m)->engine());
Q_ASSERT(m->as<QQmlSqlDatabaseWrapper>());
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, static_cast<QQmlSqlDatabaseWrapper *>(m));
+ const QQmlSqlDatabaseWrapper *r = static_cast<const QQmlSqlDatabaseWrapper *>(m);
if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
return Object::getIndexed(m, index, hasProperty);
- return qmlsqldatabase_rows_index(r, scope.engine, index, hasProperty);
+ return qmlsqldatabase_rows_index(r, r->engine(), index, hasProperty);
}
static ReturnedValue qmlsqldatabase_rows_item(CallContext *ctx)
@@ -285,13 +284,13 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
if (query.prepare(sql)) {
if (ctx->argc() > 1) {
ScopedValue values(scope, ctx->args()[1]);
- if (values->asArrayObject()) {
+ 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, scope.engine->toVariant((v = array->getIndexed(ii)), -1));
- } else if (values->asObject()) {
+ } else if (values->as<Object>()) {
ScopedObject object(scope, values);
ObjectIterator it(scope, object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
ScopedValue key(scope);
@@ -304,7 +303,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
if (key->isString()) {
query.bindValue(key->stringValue()->toQString(), v);
} else {
- assert(key->isInteger());
+ Q_ASSERT(key->isInteger());
query.bindValue(key->integerValue(), v);
}
}
@@ -401,7 +400,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx)
db.transaction();
ScopedCallData callData(scope, 1);
- callData->thisObject = scope.engine->globalObject();
+ callData->thisObject = scope.engine->globalObject;
callData->args[0] = w;
TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
@@ -433,7 +432,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re
if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
V4THROW_REFERENCE("Not a SQLDatabase object");
- FunctionObject *callback = ctx->argc() ? ctx->args()[0].asFunctionObject() : 0;
+ const FunctionObject *callback = ctx->argc() ? ctx->args()[0].as<FunctionObject>() : 0;
if (!callback)
V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback"));
@@ -450,7 +449,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re
db.transaction();
if (callback) {
ScopedCallData callData(scope, 1);
- callData->thisObject = scope.engine->globalObject();
+ callData->thisObject = scope.engine->globalObject;
callData->args[0] = w;
TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
callback->call(callData);
@@ -673,7 +672,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
QString dbversion = (v = (*args)[1])->toQStringNoThrow();
QString dbdescription = (v = (*args)[2])->toQStringNoThrow();
int dbestimatedsize = (v = (*args)[3])->toInt32();
- FunctionObject *dbcreationCallback = (v = (*args)[4])->asFunctionObject();
+ FunctionObject *dbcreationCallback = (v = (*args)[4])->as<FunctionObject>();
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(dbname.toUtf8());
@@ -724,7 +723,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
if (created && dbcreationCallback) {
Scope scope(ctx);
ScopedCallData callData(scope, 1);
- callData->thisObject = scope.engine->globalObject();
+ callData->thisObject = scope.engine->globalObject;
callData->args[0] = db;
dbcreationCallback->call(callData);
}
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 039ee63f07..4c48611e79 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -613,12 +613,19 @@ Item {
\li blue(x, y) Returns the blue channel value of the pixel at \a x, \a y position
\li alpha(x, y) Returns the alpha channel value of the pixel at \a x, \a y position
\li pixel(x, y) Returns the color value of the pixel at \a x, \a y position
+ \li equals(image) Returns \c true if this image is identical to \a image -
+ see \l QImage::operator== (since 5.6)
+
For example:
\code
var image = grabImage(rect);
compare(image.red(10, 10), 255);
compare(image.pixel(20, 20), Qt.rgba(255, 0, 0, 255));
+
+ rect.width += 10;
+ var newImage = grabImage(rect);
+ verify(!newImage.equals(image));
\endcode
\endlist
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
index b078edcbc6..832f484c13 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
@@ -36,7 +36,7 @@
#include <qqmlcontext.h>
#include <private/qqmlengine_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp
index 32cde7c126..5e244ba02c 100644
--- a/src/particles/qquickcustomparticle.cpp
+++ b/src/particles/qquickcustomparticle.cpp
@@ -370,10 +370,10 @@ QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
}
}
- NodeHashConstIt it = m_nodes.begin();
+ NodeHashConstIt it = m_nodes.cbegin();
rootNode = it.value();
rootNode->setFlag(QSGNode::OwnsMaterial, true);
- const NodeHashConstIt cend = m_nodes.end();
+ NodeHashConstIt cend = m_nodes.cend();
for (++it; it != cend; ++it)
rootNode->appendChildNode(it.value());
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index c0e1b4e422..a17949130f 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -1156,7 +1156,9 @@ QQuickParticleData* QQuickImageParticle::getShadowDatum(QQuickParticleData* datu
QQuickParticleGroupData* gd = m_system->groupData[datum->group];
if (!m_shadowData.contains(datum->group)) {
QVector<QQuickParticleData*> data;
- for (int i=0; i<gd->size(); i++){
+ const int gdSize = gd->size();
+ data.reserve(gdSize);
+ for (int i = 0; i < gdSize; i++) {
QQuickParticleData* datum = new QQuickParticleData(m_system);
*datum = *(gd->data[i]);
data << datum;
diff --git a/src/particles/qquickimageparticle_p.h b/src/particles/qquickimageparticle_p.h
index 7d7d98dab6..16832d76dc 100644
--- a/src/particles/qquickimageparticle_p.h
+++ b/src/particles/qquickimageparticle_p.h
@@ -175,13 +175,12 @@ class QQuickImageParticle : public QQuickParticlePainter
Q_PROPERTY(bool spritesInterpolate READ spritesInterpolate WRITE setSpritesInterpolate NOTIFY spritesInterpolateChanged)
Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
- Q_ENUMS(EntryEffect)
- Q_ENUMS(Status)
public:
explicit QQuickImageParticle(QQuickItem *parent = 0);
virtual ~QQuickImageParticle();
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
QQmlListProperty<QQuickSprite> sprites();
QQuickStochasticEngine* spriteEngine() {return m_spriteEngine;}
@@ -191,6 +190,7 @@ public:
Fade = 1,
Scale = 2
};
+ Q_ENUM(EntryEffect)
enum PerformanceLevel{//TODO: Expose?
Unknown = 0,
diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h
index 65e2a34aa7..68f01e3f6a 100644
--- a/src/particles/qquickparticleemitter_p.h
+++ b/src/particles/qquickparticleemitter_p.h
@@ -67,7 +67,6 @@ class QQuickParticleEmitter : public QQuickItem
Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
Q_PROPERTY(qreal velocityFromMovement READ velocityFromMovement WRITE setVelocityFromMovement NOTIFY velocityFromMovementChanged)
- Q_ENUMS(Lifetime)
public:
explicit QQuickParticleEmitter(QQuickItem *parent = 0);
virtual ~QQuickParticleEmitter();
@@ -76,6 +75,7 @@ public:
enum Lifetime {
InfiniteLife = QQuickParticleSystem::maxLife
};
+ Q_ENUM(Lifetime)
bool enabled() const
{
diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp
index affd19d981..617c33d6e5 100644
--- a/src/particles/qquickparticlesystem.cpp
+++ b/src/particles/qquickparticlesystem.cpp
@@ -1025,6 +1025,7 @@ void QQuickParticleSystem::createEngine()
}
m_groups = newList;
QList<QQuickStochasticState*> states;
+ states.reserve(m_groups.count());
foreach (QQuickParticleGroup* g, m_groups)
states << (QQuickStochasticState*)g;
diff --git a/src/particles/qquickpointattractor_p.h b/src/particles/qquickpointattractor_p.h
index aa2c9f2083..31038aeba4 100644
--- a/src/particles/qquickpointattractor_p.h
+++ b/src/particles/qquickpointattractor_p.h
@@ -45,8 +45,6 @@ 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)
- Q_ENUMS(AffectableParameters)
- Q_ENUMS(Proportion)
public:
enum Proportion{
@@ -56,12 +54,14 @@ public:
InverseLinear,
InverseQuadratic
};
+ Q_ENUM(Proportion)
enum AffectableParameters {
Position,
Velocity,
Acceleration
};
+ Q_ENUM(AffectableParameters)
explicit QQuickAttractorAffector(QQuickItem *parent = 0);
diff --git a/src/particles/qquicktrailemitter_p.h b/src/particles/qquicktrailemitter_p.h
index d1213158d8..fd11a07056 100644
--- a/src/particles/qquicktrailemitter_p.h
+++ b/src/particles/qquicktrailemitter_p.h
@@ -48,11 +48,11 @@ class QQuickTrailEmitter : public QQuickParticleEmitter
Q_PROPERTY(qreal emitHeight READ emitterYVariation WRITE setEmitterYVariation NOTIFY emitterYVariationChanged)
Q_PROPERTY(qreal emitWidth READ emitterXVariation WRITE setEmitterXVariation NOTIFY emitterXVariationChanged)
- Q_ENUMS(EmitSize)
public:
enum EmitSize {
ParticleSize = -2//Anything less than 0 will do
};
+ Q_ENUM(EmitSize)
explicit QQuickTrailEmitter(QQuickItem *parent = 0);
virtual void emitWindow(int timeStamp);
virtual void reset();
diff --git a/src/particles/qquickv4particledata_p.h b/src/particles/qquickv4particledata_p.h
index f211ec7e7d..c29c7e1134 100644
--- a/src/particles/qquickv4particledata_p.h
+++ b/src/particles/qquickv4particledata_p.h
@@ -36,7 +36,7 @@
#include <private/qv8engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickwander_p.h b/src/particles/qquickwander_p.h
index 49c49c560e..93ad8516a7 100644
--- a/src/particles/qquickwander_p.h
+++ b/src/particles/qquickwander_p.h
@@ -54,7 +54,6 @@ 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)
- Q_ENUMS(AffectableParameters)
public:
enum AffectableParameters {
@@ -62,6 +61,7 @@ public:
Velocity,
Acceleration
};
+ Q_ENUM(AffectableParameters)
explicit QQuickWanderAffector(QQuickItem *parent = 0);
~QQuickWanderAffector();
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
new file mode 100644
index 0000000000..344700b8fd
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlocalclientconnection.h"
+#include "qpacketprotocol.h"
+
+#include <QtCore/qplugin.h>
+#include <QtNetwork/qlocalsocket.h>
+
+#include <private/qqmldebugserver_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QLocalClientConnectionPrivate {
+public:
+ QLocalClientConnectionPrivate();
+
+ bool block;
+ QString filename;
+ QLocalSocket *socket;
+ QPacketProtocol *protocol;
+ QQmlDebugServer *debugServer;
+};
+
+QLocalClientConnectionPrivate::QLocalClientConnectionPrivate() :
+ block(false),
+ socket(0),
+ protocol(0),
+ debugServer(0)
+{
+}
+
+QLocalClientConnection::QLocalClientConnection() :
+ d_ptr(new QLocalClientConnectionPrivate)
+{
+}
+
+QLocalClientConnection::~QLocalClientConnection()
+{
+ if (isConnected())
+ disconnect();
+ delete d_ptr;
+}
+
+void QLocalClientConnection::setServer(QQmlDebugServer *server)
+{
+ Q_D(QLocalClientConnection);
+ d->debugServer = server;
+}
+
+bool QLocalClientConnection::isConnected() const
+{
+ Q_D(const QLocalClientConnection);
+ return d->socket && d->socket->state() == QLocalSocket::ConnectedState;
+}
+
+void QLocalClientConnection::send(const QList<QByteArray> &messages)
+{
+ Q_D(QLocalClientConnection);
+
+ if (!isConnected() || !d->protocol || !d->socket)
+ return;
+
+ foreach (const QByteArray &message, messages) {
+ QPacket pack;
+ pack.writeRawData(message.data(), message.length());
+ d->protocol->send(pack);
+ }
+ d->socket->flush();
+}
+
+void QLocalClientConnection::disconnect()
+{
+ Q_D(QLocalClientConnection);
+
+ while (d->socket && d->socket->bytesToWrite() > 0)
+ d->socket->waitForBytesWritten();
+
+ // protocol might still be processing packages at this point
+ d->protocol->deleteLater();
+ d->protocol = 0;
+ d->socket->deleteLater();
+ d->socket = 0;
+}
+
+bool QLocalClientConnection::waitForMessage()
+{
+ Q_D(QLocalClientConnection);
+ return d->protocol->waitForReadyRead(-1);
+}
+
+bool QLocalClientConnection::setPortRange(int portFrom, int portTo, bool block,
+ const QString &hostaddress)
+{
+ Q_UNUSED(portFrom);
+ Q_UNUSED(portTo);
+ Q_UNUSED(block);
+ Q_UNUSED(hostaddress);
+ return false;
+}
+
+bool QLocalClientConnection::setFileName(const QString &filename, bool block)
+{
+ Q_D(QLocalClientConnection);
+ d->filename = filename;
+ d->block = block;
+ return connect();
+}
+
+void QLocalClientConnection::waitForConnection()
+{
+ Q_D(QLocalClientConnection);
+ d->socket->waitForConnected(-1);
+}
+
+bool QLocalClientConnection::connect()
+{
+ Q_D(QLocalClientConnection);
+
+ d->socket = new QLocalSocket;
+ d->socket->setParent(this);
+ QObject::connect(d->socket, SIGNAL(connected()), this, SLOT(connectionEstablished()));
+ d->socket->connectToServer(d->filename);
+ qDebug("QML Debugger: Connecting to socket %s...",
+ d->filename.toLatin1().constData());
+ return true;
+}
+
+void QLocalClientConnection::readyRead()
+{
+ Q_D(QLocalClientConnection);
+ if (!d->protocol)
+ return;
+
+ QPacket packet = d->protocol->read();
+
+ QByteArray content = packet.data();
+ d->debugServer->receiveMessage(content);
+}
+
+void QLocalClientConnection::connectionEstablished()
+{
+ Q_D(QLocalClientConnection);
+
+ d->protocol = new QPacketProtocol(d->socket, this);
+ QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ QObject::connect(d->protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket()));
+
+ if (d->block)
+ d->protocol->waitForReadyRead(-1);
+}
+
+void QLocalClientConnection::invalidPacket()
+{
+ qWarning("QML Debugger: Received a corrupted packet! Giving up ...");
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlabstractexpression.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.h
index c55c86952c..424337900b 100644
--- a/src/qml/qml/qqmlabstractexpression.cpp
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.h
@@ -31,63 +31,48 @@
**
****************************************************************************/
-#include "qqmlabstractexpression_p.h"
+#ifndef QLOCALCLIENTCONNECTION_H
+#define QLOCALCLIENTCONNECTION_H
-QT_BEGIN_NAMESPACE
+#include <private/qqmldebugserverconnection_p.h>
-QQmlAbstractExpression::QQmlAbstractExpression()
-: m_prevExpression(0), m_nextExpression(0)
-{
-}
+QT_BEGIN_NAMESPACE
-QQmlAbstractExpression::~QQmlAbstractExpression()
+class QQmlDebugServer;
+class QLocalClientConnectionPrivate;
+class QLocalClientConnection : public QObject, public QQmlDebugServerConnection
{
- if (m_prevExpression) {
- *m_prevExpression = m_nextExpression;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = m_prevExpression;
- }
-
- if (m_context.isT2())
- m_context.asT2()->_s = 0;
-}
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QLocalClientConnection)
+ Q_DISABLE_COPY(QLocalClientConnection)
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlDebugServerConnection")
+ Q_INTERFACES(QQmlDebugServerConnection)
-QQmlContextData *QQmlAbstractExpression::context() const
-{
- if (m_context.isT1()) return m_context.asT1();
- else return m_context.asT2()->_c;
-}
+public:
+ QLocalClientConnection();
+ ~QLocalClientConnection();
-void QQmlAbstractExpression::setContext(QQmlContextData *context)
-{
- if (m_prevExpression) {
- *m_prevExpression = m_nextExpression;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = m_prevExpression;
- m_prevExpression = 0;
- m_nextExpression = 0;
- }
+ void setServer(QQmlDebugServer *server);
+ bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress);
+ bool setFileName(const QString &filename, bool block);
- if (m_context.isT1()) m_context = context;
- else m_context.asT2()->_c = context;
+ bool isConnected() const;
+ void send(const QList<QByteArray> &messages);
+ void disconnect();
+ bool waitForMessage();
- if (context) {
- m_nextExpression = context->expressions;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = &m_nextExpression;
- m_prevExpression = &context->expressions;
- context->expressions = this;
- }
-}
+ void waitForConnection();
+ bool connect();
-void QQmlAbstractExpression::refresh()
-{
-}
+private Q_SLOTS:
+ void readyRead();
+ void connectionEstablished();
+ void invalidPacket();
-bool QQmlAbstractExpression::isValid() const
-{
- return context() != 0;
-}
+private:
+ QLocalClientConnectionPrivate *d_ptr;
+};
QT_END_NAMESPACE
+#endif // QLOCALCLIENTCONNECTION_H
diff --git a/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pri b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pri
new file mode 100644
index 0000000000..7635523e9b
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pri
@@ -0,0 +1,14 @@
+QT += core-private
+
+SOURCES += \
+ $$PWD/qlocalclientconnection.cpp \
+ $$PWD/../shared/qpacketprotocol.cpp
+
+HEADERS += \
+ $$PWD/qlocalclientconnection.h \
+ $$PWD/../shared/qpacketprotocol.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += $$PWD/qlocalclientconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
new file mode 100644
index 0000000000..b060154933
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
@@ -0,0 +1,8 @@
+TARGET = qmldbg_local
+QT = qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QLocalClientConnection
+load(qt_plugin)
+
+include(qmldbg_local.pri)
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
index e61c421bfa..9255e49364 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
@@ -211,6 +211,7 @@ void QQuickViewInspector::setSelectedItems(const QList<QQuickItem *> &items)
return;
QList<QObject*> objectList;
+ objectList.reserve(items.count());
foreach (QQuickItem *item, items)
objectList << item;
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 2ae4edfce4..f7c0673c19 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -146,6 +146,13 @@ bool QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block,
return listen();
}
+bool QTcpServerConnection::setFileName(const QString &fileName, bool block)
+{
+ Q_UNUSED(fileName);
+ Q_UNUSED(block);
+ return false;
+}
+
void QTcpServerConnection::waitForConnection()
{
Q_D(QTcpServerConnection);
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
index 942fb6e12c..496d328a11 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
@@ -54,6 +54,7 @@ public:
void setServer(QQmlDebugServer *server);
bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress);
+ bool setFileName(const QString &fileName, bool block);
bool isConnected() const;
void send(const QList<QByteArray> &messages);
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 3bc48a6b33..585f80138b 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS = qmldbg_tcp
+SUBDIRS = qmldbg_tcp qmldbg_local
qtHaveModule(quick): SUBDIRS += qmldbg_qtquick2
diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.cpp b/src/plugins/qmltooling/shared/abstractviewinspector.cpp
index e718cf022f..06f622a65e 100644
--- a/src/plugins/qmltooling/shared/abstractviewinspector.cpp
+++ b/src/plugins/qmltooling/shared/abstractviewinspector.cpp
@@ -372,6 +372,7 @@ void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
ds << QByteArray(EVENT) << m_eventId++ << QByteArray(SELECT);
QList<int> debugIds;
+ debugIds.reserve(objects.count());
foreach (QObject *object, objects)
debugIds << QQmlDebugService::idForObject(object);
ds << debugIds;
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 63833504f1..cc9da2817a 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -33,7 +33,7 @@
#include "qqmlirbuilder_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljslexer_p.h>
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 46b67d5983..61b538e726 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -104,11 +104,10 @@ bool QQmlTypeCompiler::compile()
}
if (ref->type->containsRevisionedAttributes()) {
- QQmlError cacheError;
ref->typePropertyCache = engine->cache(ref->type,
- resolvedType->minorVersion,
- cacheError);
+ resolvedType->minorVersion);
if (!ref->typePropertyCache) {
+ QQmlError cacheError;
cacheError.setColumn(resolvedType->location.column);
cacheError.setLine(resolvedType->location.line);
recordError(cacheError);
@@ -696,6 +695,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
const int paramCount = s->parameters->count;
QList<QByteArray> names;
+ names.reserve(paramCount);
QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
if (paramCount) {
@@ -1022,10 +1022,10 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
}
- QHash<QString, QStringList>::ConstIterator entry = customSignals.find(propertyName);
+ QHash<QString, QStringList>::ConstIterator entry = customSignals.constFind(propertyName);
if (entry == customSignals.constEnd() && propertyName.endsWith(QStringLiteral("Changed"))) {
QString alternateName = propertyName.mid(0, propertyName.length() - static_cast<int>(strlen("Changed")));
- entry = customSignals.find(alternateName);
+ entry = customSignals.constFind(alternateName);
}
if (entry == customSignals.constEnd()) {
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 9168889c8c..ea82d07e69 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -33,6 +33,7 @@
#include "qv4codegen_p.h"
#include "qv4util_p.h"
+#include "qv4engine_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
@@ -43,7 +44,7 @@
#include <QtCore/QStack>
#include <private/qqmljsast_p.h>
#include <private/qv4string_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4context_p.h>
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 5d954eb4fc..20db5edaa3 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -33,7 +33,7 @@
#include "qv4compileddata_p.h"
#include "qv4jsir_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qv4engine_p.h>
#include <private/qv4function_p.h>
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 450889c275..ba4bde7a31 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -35,7 +35,7 @@
#include <qv4compileddata_p.h>
#include <qv4isel_p.h>
#include <private/qv4string_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QV4::Compiler::StringTableGenerator::StringTableGenerator()
{
@@ -44,8 +44,8 @@ QV4::Compiler::StringTableGenerator::StringTableGenerator()
int QV4::Compiler::StringTableGenerator::registerString(const QString &str)
{
- QHash<QString, int>::ConstIterator it = stringToId.find(str);
- if (it != stringToId.end())
+ QHash<QString, int>::ConstIterator it = stringToId.constFind(str);
+ if (it != stringToId.cend())
return *it;
stringToId.insert(str, strings.size());
strings.append(str);
@@ -169,6 +169,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *arg
// ### re-use existing class definitions.
QList<CompiledData::JSClassMember> members;
+ members.reserve(count);
IR::ExprList *it = args;
for (int i = 0; i < count; ++i, it = it->next) {
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index eb78a0c054..59099159c1 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -447,7 +447,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backend
foreach (IR::Function *irFunction, irModule->functions)
compilationUnit->codeRefs[i++] = codeRefs[irFunction];
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
- result.take(compilationUnit.take());
+ result.adopt(compilationUnit.take());
return result;
}
@@ -1444,7 +1444,7 @@ ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &in
void InstructionSelection::patchJumpAddresses()
{
typedef QHash<IR::BasicBlock *, QVector<ptrdiff_t> >::ConstIterator PatchIt;
- for (PatchIt i = _patches.begin(), ei = _patches.end(); i != ei; ++i) {
+ for (PatchIt i = _patches.cbegin(), ei = _patches.cend(); i != ei; ++i) {
Q_ASSERT(_addrs.contains(i.key()));
ptrdiff_t target = _addrs.value(i.key());
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 54b184b4eb..46b9c784d2 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -36,7 +36,7 @@
#include "qv4jsir_p.h"
#include "qv4isel_p.h"
#include "qv4isel_util_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qqmlpropertycache_p.h>
#endif
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 559c492dfd..58afa004a0 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -50,6 +50,7 @@ struct Q_QML_EXPORT QQmlDebuggingEnabler
QQmlDebuggingEnabler(bool printWarning = true);
static bool startTcpDebugServer(int port, StartMode mode = DoNotWaitForClient,
const QString &hostName = QString());
+ static bool connectToLocalDebugger(const QString &socketFileName, bool block = false);
};
// Execute code in constructor before first QQmlEngine is instantiated
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
index b0302181ee..0e6a182b1a 100644
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ b/src/qml/debugger/qqmldebugserver.cpp
@@ -51,7 +51,7 @@
#include <private/qobject_p.h>
#include <private/qcoreapplication_p.h>
-#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
+#if defined(QT_STATIC) && !defined(QT_NO_QML_DEBUGGER) && !defined(QT_NO_LIBRARY)
#include "../../plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h"
#endif
@@ -94,7 +94,9 @@ const int protocolVersion = 1;
int QQmlDebugServer::s_dataStreamVersion = QDataStream::Qt_4_7;
// print detailed information about loading of plugins
+#ifndef QT_NO_LIBRARY
DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
+#endif
class QQmlDebugServerThread;
@@ -104,8 +106,11 @@ class QQmlDebugServerPrivate : public QObjectPrivate
public:
QQmlDebugServerPrivate();
- bool start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName);
+ bool init(const QString &pluginName, bool block);
+
+ template<class Action>
+ static bool enable(Action action);
+
void advertisePlugins();
void cleanup();
QQmlDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
@@ -136,7 +141,9 @@ public:
QMutex helloMutex;
QWaitCondition helloCondition;
QQmlDebugServerThread *thread;
+#ifndef QT_NO_LIBRARY
QPluginLoader loader;
+#endif
QAtomicInt changeServiceStateCalls;
private:
@@ -164,6 +171,12 @@ public:
m_hostAddress = hostAddress;
}
+ void setFileName(const QString &fileName, bool block)
+ {
+ m_fileName = fileName;
+ m_block = block;
+ }
+
void run();
private:
@@ -172,6 +185,7 @@ private:
int m_portTo;
bool m_block;
QString m_hostAddress;
+ QString m_fileName;
};
QQmlDebugServerPrivate::QQmlDebugServerPrivate() :
@@ -199,7 +213,11 @@ void QQmlDebugServerPrivate::advertisePlugins()
QQmlDebugStream out(&message, QIODevice::WriteOnly);
QStringList pluginNames;
QList<float> pluginVersions;
- foreach (QQmlDebugService *service, plugins.values()) {
+ const QList<QQmlDebugService *> debugServices = plugins.values();
+ const int count = debugServices.count();
+ pluginNames.reserve(count);
+ pluginVersions.reserve(count);
+ foreach (QQmlDebugService *service, debugServices) {
pluginNames << service->name();
pluginVersions << service->version();
}
@@ -282,6 +300,8 @@ QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
loader.unload();
}
+#else
+ Q_UNUSED(pluginName);
#endif
return 0;
}
@@ -291,7 +311,7 @@ void QQmlDebugServerThread::run()
QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
Q_ASSERT_X(wrapper != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
QQmlDebugServer *server = &wrapper->m_instance;
-#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
+#if defined(QT_STATIC) && !defined(QT_NO_QML_DEBUGGER) && !defined(QT_NO_LIBRARY)
QQmlDebugServerConnection *connection
= new QTcpServerConnection;
#else
@@ -300,10 +320,19 @@ void QQmlDebugServerThread::run()
#endif
if (connection) {
connection->setServer(server);
- if (!connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress)) {
- delete connection;
- return;
+
+ if (m_fileName.isEmpty()) {
+ if (!connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress)) {
+ delete connection;
+ return;
+ }
+ } else {
+ if (!connection->setFileName(m_fileName, m_block)) {
+ delete connection;
+ return;
+ }
}
+
server->d_func()->connection = connection;
if (m_block)
connection->waitForConnection();
@@ -367,8 +396,7 @@ static void cleanupOnShutdown()
wrapper->cleanup();
}
-bool QQmlDebugServerPrivate::start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName)
+bool QQmlDebugServerPrivate::init(const QString &pluginName, bool block)
{
if (!QQmlEnginePrivate::qml_debugging_enabled)
return false;
@@ -389,9 +417,7 @@ bool QQmlDebugServerPrivate::start(int portFrom, int portTo, bool block, const Q
thread->setObjectName(QStringLiteral("QQmlDebugServerThread"));
thread->setPluginName(pluginName);
- thread->setPortRange(portFrom, portTo == -1 ? portFrom : portTo, block, hostAddress);
blockingMode = block;
- thread->start();
return true;
}
@@ -408,6 +434,7 @@ QQmlDebugServer::QQmlDebugServer()
bool block = false;
bool ok = false;
QString hostAddress;
+ QString fileName;
// format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
if (!appD->qmljsDebugArgumentsString().isEmpty()) {
@@ -422,8 +449,8 @@ QQmlDebugServer::QQmlDebugServer()
QString pluginName;
QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString()
.split(QLatin1Char(','));
- QStringList::const_iterator argsItEnd = lstjsDebugArguments.end();
- QStringList::const_iterator argsIt = lstjsDebugArguments.begin();
+ QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend();
+ QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin();
for (; argsIt != argsItEnd; ++argsIt) {
const QString strArgument = *argsIt;
if (strArgument.startsWith(QLatin1String("port:"))) {
@@ -442,6 +469,10 @@ QQmlDebugServer::QQmlDebugServer()
hostAddress = strArgument.mid(5);
} else if (strArgument == QLatin1String("block")) {
block = true;
+ } else if (strArgument.startsWith(QLatin1String("file:"))) {
+ pluginName = QLatin1String("qmldbg_local");
+ fileName = strArgument.mid(5);
+ ok = !fileName.isEmpty();
} else {
qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
"detected. Ignoring the same.")
@@ -451,7 +482,13 @@ QQmlDebugServer::QQmlDebugServer()
if (ok) {
Q_D(QQmlDebugServer);
- d->start(portFrom, portTo, block, hostAddress, pluginName);
+ if (d->init(pluginName, block)) {
+ if (!fileName.isEmpty())
+ d->thread->setFileName(fileName, block);
+ else
+ d->thread->setPortRange(portFrom, portTo, block, hostAddress);
+ d->thread->start();
+ }
} else {
qWarning() << QString(QLatin1String(
"QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
@@ -505,7 +542,11 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message)
QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
QStringList pluginNames;
QList<float> pluginVersions;
- foreach (QQmlDebugService *service, d->plugins.values()) {
+ const QList<QQmlDebugService*> debugServices = d->plugins.values();
+ const int count = debugServices.count();
+ pluginNames.reserve(count);
+ pluginVersions.reserve(count);
+ foreach (QQmlDebugService *service, debugServices) {
pluginNames << service->name();
pluginVersions << service->version();
}
@@ -719,6 +760,7 @@ void QQmlDebugServer::sendMessages(QQmlDebugService *service,
const QList<QByteArray> &messages)
{
QList<QByteArray> prefixedMessages;
+ prefixedMessages.reserve(messages.count());
foreach (const QByteArray &message, messages) {
QByteArray prefixed;
QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
@@ -730,7 +772,44 @@ void QQmlDebugServer::sendMessages(QQmlDebugService *service,
Q_ARG(QList<QByteArray>, prefixedMessages));
}
-bool QQmlDebugServer::enable(int portFrom, int portTo, bool block, const QString &hostAddress)
+struct StartTcpServerAction {
+ int portFrom;
+ int portTo;
+ bool block;
+ QString hostAddress;
+
+ StartTcpServerAction(int portFrom, int portTo, bool block, const QString &hostAddress) :
+ portFrom(portFrom), portTo(portTo), block(block), hostAddress(hostAddress) {}
+
+ bool operator()(QQmlDebugServerPrivate *d)
+ {
+ if (!d->init(QLatin1String("qmldbg_tcp"), block))
+ return false;
+ d->thread->setPortRange(portFrom, portTo == -1 ? portFrom : portTo, block, hostAddress);
+ d->thread->start();
+ return true;
+ }
+};
+
+struct ConnectToLocalAction {
+ QString fileName;
+ bool block;
+
+ ConnectToLocalAction(const QString &fileName, bool block) :
+ fileName(fileName), block(block) {}
+
+ bool operator()(QQmlDebugServerPrivate *d)
+ {
+ if (!d->init(QLatin1String("qmldbg_local"), block))
+ return false;
+ d->thread->setFileName(fileName, block);
+ d->thread->start();
+ return true;
+ }
+};
+
+template<class Action>
+bool QQmlDebugServerPrivate::enable(Action action)
{
#ifndef QT_NO_QML_DEBUGGER
QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
@@ -739,7 +818,7 @@ bool QQmlDebugServer::enable(int portFrom, int portTo, bool block, const QString
QQmlDebugServerPrivate *d = wrapper->m_instance.d_func();
if (d->thread)
return false;
- if (!d->start(portFrom, portTo, block, hostAddress, QLatin1String("qmldbg_tcp")))
+ if (!action(d))
return false;
while (!wrapper->m_instance.hasConnection()) {
if (!wrapper->m_instance.hasThread())
@@ -755,6 +834,57 @@ bool QQmlDebugServer::enable(int portFrom, int portTo, bool block, const QString
#endif
}
+/*!
+ * \enum QQmlDebuggingEnabler::StartMode
+ *
+ * Defines the debug server's start behavior. You can interrupt QML engines starting while a debug
+ * client is connecting, in order to set breakpoints in or profile startup code.
+ *
+ * \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
+ * \value WaitForClient If a QML engine starts while the debug services are connecting,
+ * interrupt it until they are done.
+ */
+
+/*!
+ * Enables debugging for QML engines created after calling this function. The debug server will
+ * listen on \a port at \a hostName and block the QML engine until it receives a connection if
+ * \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
+ * specified it will listen on all available interfaces. You can only start one debug server at a
+ * time. A debug server may have already been started if the -qmljsdebugger= command line argument
+ * was given. This method returns \c true if a new debug server was successfully started, or
+ * \c false otherwise.
+ */
+bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ return QQmlDebugServerPrivate::enable(StartTcpServerAction(port, port, mode == WaitForClient, hostName));
+#else
+ Q_UNUSED(port);
+ Q_UNUSED(block);
+ Q_UNUSED(hostName);
+ return false;
+#endif
+}
+
+/*!
+ * Enables debugging for QML engines created after calling this function. The debug server will
+ * connect to a debugger waiting on a local socket at the given \a socketFileName and block the QML
+ * engine until the connection is established if \a block is true. If \a block is not specified it
+ * won't block. You can only start one debug server at a time. A debug server may have already been
+ * started if the -qmljsdebugger= command line argument was given. This method returns \c true if a
+ * new debug server was successfully started, or \c false otherwise.
+ */
+bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, bool block)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ return QQmlDebugServerPrivate::enable(ConnectToLocalAction(socketFileName, block));
+#else
+ Q_UNUSED(fileName);
+ Q_UNUSED(block);
+ return false;
+#endif
+}
+
void QQmlDebugServer::wakeEngine(QQmlEngine *engine)
{
// to be executed in debugger thread
diff --git a/src/qml/debugger/qqmldebugserver_p.h b/src/qml/debugger/qqmldebugserver_p.h
index b2bd0b2463..f4026ca85f 100644
--- a/src/qml/debugger/qqmldebugserver_p.h
+++ b/src/qml/debugger/qqmldebugserver_p.h
@@ -79,7 +79,6 @@ public:
void receiveMessage(const QByteArray &message);
void sendMessages(QQmlDebugService *service, const QList<QByteArray> &messages);
- static bool enable(int portFrom, int portTo, bool block, const QString &hostAddress);
private slots:
void wakeEngine(QQmlEngine *engine);
diff --git a/src/qml/debugger/qqmldebugserverconnection_p.h b/src/qml/debugger/qqmldebugserverconnection_p.h
index 9170238b46..cfdf85a9b6 100644
--- a/src/qml/debugger/qqmldebugserverconnection_p.h
+++ b/src/qml/debugger/qqmldebugserverconnection_p.h
@@ -60,6 +60,7 @@ public:
virtual void setServer(QQmlDebugServer *server) = 0;
virtual bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress) = 0;
+ virtual bool setFileName(const QString &fileName, bool block) = 0;
virtual bool isConnected() const = 0;
virtual void send(const QList<QByteArray> &messages) = 0;
virtual void disconnect() = 0;
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 9cdfc34ff1..db4f1c1152 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -62,7 +62,6 @@ class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject
Q_DISABLE_COPY(QQmlDebugService)
public:
- explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
~QQmlDebugService();
QString name() const;
@@ -88,6 +87,7 @@ public:
static bool blockingMode();
protected:
+ explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
QQmlDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
State registerService();
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
index da01d00f17..0a3ddc6db5 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/qml/debugger/qqmlenginedebugservice.cpp
@@ -192,6 +192,7 @@ QVariant QQmlEngineDebugService::valueContents(QVariant value) const
QVariantList contents;
QVariantList list = value.toList();
int count = list.size();
+ contents.reserve(count);
for (int i = 0; i < count; i++)
contents << valueContents(list.at(i));
return contents;
@@ -277,13 +278,9 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
QQmlData *ddata = QQmlData::get(object);
if (ddata && ddata->signalHandlers) {
- QQmlAbstractBoundSignal *signalHandler = ddata->signalHandlers;
+ QQmlBoundSignal *signalHandler = ddata->signalHandlers;
while (signalHandler) {
- if (!dumpProperties) {
- signalHandler = signalHandler->m_nextSignal;
- continue;
- }
QQmlObjectProperty prop;
prop.type = QQmlObjectProperty::SignalProperty;
prop.hasNotifySignal = false;
@@ -292,7 +289,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
prop.value = expr->expression();
QObject *scope = expr->scopeObject();
if (scope) {
- QString methodName = QString::fromLatin1(QMetaObjectPrivate::signal(scope->metaObject(), signalHandler->index()).name());
+ QString methodName = QString::fromLatin1(QMetaObjectPrivate::signal(scope->metaObject(), signalHandler->signalIndex()).name());
if (!methodName.isEmpty()) {
prop.name = QLatin1String("on") + methodName[0].toUpper()
+ methodName.mid(1);
@@ -644,11 +641,9 @@ bool QQmlEngineDebugService::setBinding(int objectId,
filename, line, column);
QQmlPropertyPrivate::takeSignalExpression(property, qmlExpression);
} else if (property.isProperty()) {
- QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column);;
+ QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column);
binding->setTarget(property);
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, binding);
- if (oldBinding)
- oldBinding->destroy();
+ QQmlPropertyPrivate::setBinding(binding);
binding->update();
} else {
ok = false;
@@ -679,12 +674,7 @@ bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyN
if (object->property(parentProperty.toLatin1()).isValid()) {
QQmlProperty property(object, propertyName);
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(property);
- if (oldBinding) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, 0);
- if (oldBinding)
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(property);
if (property.isResettable()) {
// Note: this will reset the property in any case, without regard to states
// Right now almost no QQuickItem has reset methods for its properties (with the
@@ -762,7 +752,7 @@ bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method,
int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle());
QV4::Scope scope(v4);
- QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
+ QV4::ScopedValue v(scope, QQmlJavaScriptExpression::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
vmeMetaObject->setVmeMethod(prop->coreIndex, v);
return true;
}
diff --git a/src/qml/debugger/qqmlinspectorservice.cpp b/src/qml/debugger/qqmlinspectorservice.cpp
index 5a8c4487d9..0bc1257b75 100644
--- a/src/qml/debugger/qqmlinspectorservice.cpp
+++ b/src/qml/debugger/qqmlinspectorservice.cpp
@@ -42,8 +42,10 @@
#include <QtCore/QDir>
#include <QtCore/QPluginLoader>
+#ifndef QT_NO_LIBRARY
// print detailed information about loading of plugins
DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
+#endif
QT_BEGIN_NAMESPACE
@@ -140,6 +142,7 @@ void QQmlInspectorService::processMessage(const QByteArray &message)
void QQmlInspectorService::loadInspectorPlugins()
{
+#ifndef QT_NO_LIBRARY
QStringList pluginCandidates;
const QStringList paths = QCoreApplication::libraryPaths();
foreach (const QString &libPath, paths) {
@@ -150,12 +153,14 @@ void QQmlInspectorService::loadInspectorPlugins()
}
foreach (const QString &pluginPath, pluginCandidates) {
- if (pluginPath.contains(QLatin1String("qmldbg_tcp")))
- continue;
if (qmlDebugVerbose())
qDebug() << "QQmlInspector: Trying to load plugin " << pluginPath << "...";
QPluginLoader loader(pluginPath);
+ if (loader.metaData()[QLatin1String("IID")] !=
+ QLatin1String("org.qt-project.Qt.QQmlInspectorInterface"))
+ continue;
+
if (!loader.load()) {
if (qmlDebugVerbose())
qDebug() << "QQmlInspector: Error while loading: " << loader.errorString();
@@ -176,6 +181,7 @@ void QQmlInspectorService::loadInspectorPlugins()
loader.unload();
}
}
+#endif
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
index 32b7b38285..dade30e576 100644
--- a/src/qml/debugger/qv4debugservice.cpp
+++ b/src/qml/debugger/qv4debugservice.cpp
@@ -46,17 +46,10 @@
#include <QtCore/QJsonObject>
#include <QtCore/QJsonValue>
-const char *V4_CONNECT = "connect";
-const char *V4_DISCONNECT = "disconnect";
-const char *V4_BREAK_ON_SIGNAL = "breakonsignal";
-const char *V4_ADD_BREAKPOINT = "addBreakpoint";
-const char *V4_REMOVE_BREAKPOINT = "removeBreakpoint";
-const char *V4_PAUSE = "interrupt";
-const char *V4_ALL = "all";
-const char *V4_BREAK = "break";
-
-const char *V4_FILENAME = "filename";
-const char *V4_LINENUMBER = "linenumber";
+const char *const V4_CONNECT = "connect";
+const char *const V4_DISCONNECT = "disconnect";
+const char *const V4_BREAK_ON_SIGNAL = "breakonsignal";
+const char *const V4_PAUSE = "interrupt";
#define NO_PROTOCOL_TRACING
#ifdef NO_PROTOCOL_TRACING
@@ -230,7 +223,7 @@ protected:
virtual void addObject(const QString &name, const QV4::Value &value)
{
QV4::Scope scope(engine());
- QV4::ScopedObject obj(scope, value.asObject());
+ QV4::ScopedObject obj(scope, value.as<QV4::Object>());
int ref = cachedObjectRef(obj);
if (ref != -1) {
@@ -356,7 +349,7 @@ class QV4DebugServicePrivate : public QQmlConfigurableDebugServicePrivate
public:
QV4DebugServicePrivate();
- ~QV4DebugServicePrivate() { qDeleteAll(handlers.values()); }
+ ~QV4DebugServicePrivate() { qDeleteAll(handlers); }
static QByteArray packMessage(const QByteArray &command, const QByteArray &message = QByteArray())
{
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 09e5b14c97..b5765b5705 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -241,16 +241,16 @@ void Assembler::enterStandardStackFrame(const RegisterInformation &regularRegist
subPtr(TrustedImm32(frameSize), StackPointerRegister);
Address slotAddr(StackFrameRegister, 0);
- for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) {
- Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
- slotAddr.offset -= RegisterSize;
- storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr);
- }
for (int i = 0, ei = fpRegistersToSave.size(); i < ei; ++i) {
Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
slotAddr.offset -= sizeof(double);
JSC::MacroAssembler::storeDouble(fpRegistersToSave.at(i).reg<FPRegisterID>(), slotAddr);
}
+ for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) {
+ Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
+ slotAddr.offset -= RegisterSize;
+ storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr);
+ }
}
void Assembler::leaveStandardStackFrame(const RegisterInformation &regularRegistersToSave,
@@ -259,16 +259,16 @@ void Assembler::leaveStandardStackFrame(const RegisterInformation &regularRegist
Address slotAddr(StackFrameRegister, -regularRegistersToSave.size() * RegisterSize - fpRegistersToSave.size() * sizeof(double));
// restore the callee saved registers
- for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) {
- Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
- JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>());
- slotAddr.offset += sizeof(double);
- }
for (int i = regularRegistersToSave.size() - 1; i >= 0; --i) {
Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
loadPtr(slotAddr, regularRegistersToSave.at(i).reg<RegisterID>());
slotAddr.offset += RegisterSize;
}
+ for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) {
+ Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
+ JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>());
+ slotAddr.offset += sizeof(double);
+ }
Q_ASSERT(slotAddr.offset == 0);
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 3b65acb26c..f4b44ce882 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -565,6 +565,8 @@ public:
moveIntsToDouble(JSC::ARMRegisters::r0, JSC::ARMRegisters::r1, dest, FPGpr0);
#elif defined(Q_PROCESSOR_X86)
moveIntsToDouble(JSC::X86Registers::eax, JSC::X86Registers::edx, dest, FPGpr0);
+#elif defined(Q_PROCESSOR_MIPS)
+ moveIntsToDouble(JSC::MIPSRegisters::v0, JSC::MIPSRegisters::v1, dest, FPGpr0);
#else
subPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister);
Pointer tmp(StackPointerRegister, 0);
@@ -595,6 +597,14 @@ public:
destination.offset += 4;
store32(JSC::ARMRegisters::r1, destination);
}
+#elif defined(Q_PROCESSOR_MIPS)
+ void storeReturnValue(const Pointer &dest)
+ {
+ Pointer destination = dest;
+ store32(JSC::MIPSRegisters::v0, destination);
+ destination.offset += 4;
+ store32(JSC::MIPSRegisters::v1, destination);
+ }
#endif
void storeReturnValue(IR::Expr *target)
@@ -820,6 +830,8 @@ public:
else
#if OS(WINDOWS) && CPU(X86_64)
loadArgumentOnStack<argumentNumber>(value, argumentNumber);
+#elif CPU(MIPS) // Stack space for 4 arguments needs to be allocated for MIPS platforms.
+ loadArgumentOnStack<argumentNumber>(value, argumentNumber + 4);
#else // Sanity:
loadArgumentOnStack<argumentNumber - RegisterArgumentCount>(value, argumentNumber);
#endif
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index c6c8023cd7..8b051fcb3d 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -352,7 +352,9 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
}
}
- if (op == IR::OpSub) {
+ // Special cases:
+ switch (op) {
+ case IR::OpSub:
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
&& targetTemp
&& targetTemp->kind == IR::Temp::PhysicalRegister
@@ -368,11 +370,27 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
}
as->storeInt32(targetReg, target);
return true;
+
+ case IR::OpLShift:
+ case IR::OpRShift:
+ case IR::OpURShift:
+ if (IR::Const *c = rightSource->asConst()) {
+ if ((QV4::Primitive::toUInt32(c->value) & 0x1f) == 0) {
+ Assembler::RegisterID r = as->toInt32Register(leftSource, targetReg);
+ as->storeInt32(r, target);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ break;
}
Assembler::RegisterID l = as->toInt32Register(leftSource, targetReg);
if (IR::Const *c = rightSource->asConst()) { // All cases of Y = X op Const
Assembler::TrustedImm32 r(int(c->value));
+ Assembler::TrustedImm32 ur(QV4::Primitive::toUInt32(c->value) & 0x1f);
switch (op) {
case IR::OpBitAnd: as->and32(r, l, targetReg); break;
@@ -381,9 +399,9 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpAdd: as->add32(r, l, targetReg); break;
case IR::OpMul: as->mul32(r, l, targetReg); break;
- case IR::OpLShift: r.m_value &= 0x1f; as->lshift32(l, r, targetReg); break;
- case IR::OpRShift: r.m_value &= 0x1f; as->rshift32(l, r, targetReg); break;
- case IR::OpURShift: r.m_value &= 0x1f; as->urshift32(l, r, targetReg);
+ case IR::OpLShift: as->lshift32(l, ur, targetReg); break;
+ case IR::OpRShift: as->rshift32(l, ur, targetReg); break;
+ case IR::OpURShift: as->urshift32(l, ur, targetReg);
as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
@@ -415,32 +433,33 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpAdd: as->add32(l, r, targetReg); break;
case IR::OpMul: as->mul32(l, r, targetReg); break;
-#if CPU(ARM) || CPU(X86) || CPU(X86_64)
- // The ARM assembler will generate an and with 0x1f for us, and Intel will do it on the CPU.
-
+#if CPU(X86) || CPU(X86_64)
+ // Intel does the & 0x1f on the CPU, so:
case IR::OpLShift: as->lshift32(l, r, targetReg); break;
case IR::OpRShift: as->rshift32(l, r, targetReg); break;
case IR::OpURShift: as->urshift32(l, r, targetReg);
as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
#else
- case IR::OpLShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->lshift32(l, Assembler::ScratchRegister, targetReg);
- break;
-
- case IR::OpRShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->rshift32(l, Assembler::ScratchRegister, targetReg);
- break;
-
+ // Not all CPUs accept shifts over more than 31 bits, and some CPUs (like ARM) will do
+ // surprising stuff when shifting over 0 bits.
+#define CHECK_RHS(op) { \
+ as->and32(Assembler::TrustedImm32(0x1f), r, Assembler::ScratchRegister); \
+ Assembler::Jump notZero = as->branch32(Assembler::NotEqual, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); \
+ as->move(l, targetReg); \
+ Assembler::Jump done = as->jump(); \
+ notZero.link(as); \
+ op; \
+ done.link(as); \
+}
+ case IR::OpLShift: CHECK_RHS(as->lshift32(l, Assembler::ScratchRegister, targetReg)); break;
+ case IR::OpRShift: CHECK_RHS(as->rshift32(l, Assembler::ScratchRegister, targetReg)); break;
case IR::OpURShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
+ CHECK_RHS(as->urshift32(l, Assembler::ScratchRegister, targetReg));
+ as->storeUInt32(targetReg, target);
+ // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
+#undef CHECK_RHS
#endif
case IR::OpSub: // already handled before
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index da511cd1eb..09e295e4f0 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -317,7 +317,7 @@ const void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backendCompileStep()
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
- result.take(compilationUnit.take());
+ result.adopt(compilationUnit.take());
return result;
}
@@ -1383,11 +1383,14 @@ void InstructionSelection::visitRet(IR::Ret *s)
// this only happens if the method doesn't have a return statement and can
// only exit through an exception
} else if (IR::Temp *t = s->expr->asTemp()) {
-#if CPU(X86) || CPU(ARM)
+#if CPU(X86) || CPU(ARM) || CPU(MIPS)
# if CPU(X86)
Assembler::RegisterID lowReg = JSC::X86Registers::eax;
Assembler::RegisterID highReg = JSC::X86Registers::edx;
+# elif CPU(MIPS)
+ Assembler::RegisterID lowReg = JSC::MIPSRegisters::v0;
+ Assembler::RegisterID highReg = JSC::MIPSRegisters::v1;
# else // CPU(ARM)
Assembler::RegisterID lowReg = JSC::ARMRegisters::r0;
Assembler::RegisterID highReg = JSC::ARMRegisters::r1;
@@ -1477,6 +1480,9 @@ void InstructionSelection::visitRet(IR::Ret *s)
#elif CPU(ARM)
_as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
_as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+#elif CPU(MIPS)
+ _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::MIPSRegisters::v0);
+ _as->move(Assembler::TrustedImm32(retVal.tag), JSC::MIPSRegisters::v1);
#else
_as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
#endif
@@ -1504,6 +1510,9 @@ void InstructionSelection::visitRet(IR::Ret *s)
#elif CPU(ARM)
_as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
_as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+#elif CPU(MIPS)
+ _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::MIPSRegisters::v0);
+ _as->move(Assembler::TrustedImm32(retVal.tag), JSC::MIPSRegisters::v1);
#else
_as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
#endif
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index ae06a99d2a..48b7badd56 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -35,7 +35,7 @@
#include <QtCore/QDebug>
#include "qv4regalloc_p.h"
#include "qv4alloca_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <algorithm>
#if defined(Q_CC_MINGW)
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 05741f0ae5..76c768e4f9 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -346,6 +346,71 @@ public:
static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::ARMRegisters::lr); }
#endif // Linux on ARM (32 bit)
+#if defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
+ enum { RegAllocIsSupported = 1 };
+
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::MIPSRegisters::fp;
+ static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::MIPSRegisters::sp;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::MIPSRegisters::s0;
+ static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::MIPSRegisters::s1;
+ static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::MIPSRegisters::v0;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::MIPSRegisters::s2;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::MIPSRegisters::f0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::MIPSRegisters::f2;
+
+ static RegisterInformation getPlatformRegisterInfo()
+ {
+ typedef RegisterInfo RI;
+ return RegisterInformation()
+ // Note: t0, t1, t2, t3 and f16 are already used by MacroAssemblerMIPS.
+ << RI(JSC::MIPSRegisters::t4, QStringLiteral("t4"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t5, QStringLiteral("t5"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t6, QStringLiteral("t6"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t7, QStringLiteral("t7"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t8, QStringLiteral("t8"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::s0, QStringLiteral("s0"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s1, QStringLiteral("s1"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s2, QStringLiteral("s2"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s3, QStringLiteral("s3"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f4, QStringLiteral("f4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f6, QStringLiteral("f6"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f8, QStringLiteral("f8"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f10, QStringLiteral("f10"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f18, QStringLiteral("f18"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f20, QStringLiteral("f20"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f22, QStringLiteral("f22"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f24, QStringLiteral("f24"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f26, QStringLiteral("f26"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f28, QStringLiteral("f28"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ ;
+ }
+
+#undef HAVE_ALU_OPS_WITH_MEM_OPERAND
+#undef VALUE_FITS_IN_REGISTER
+ static const int RegisterSize = 4;
+
+#define ARGUMENTS_IN_REGISTERS
+ static const int RegisterArgumentCount = 4;
+ static JSC::MacroAssembler::RegisterID registerForArgument(int index)
+ {
+ static JSC::MacroAssembler::RegisterID regs[RegisterArgumentCount] = {
+ JSC::MIPSRegisters::a0,
+ JSC::MIPSRegisters::a1,
+ JSC::MIPSRegisters::a2,
+ JSC::MIPSRegisters::a3
+ };
+
+ Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
+ return regs[index];
+ };
+
+ static const int StackAlignment = 8;
+ static const int StackShadowSpace = 4 * RegisterSize; // Stack space for 4 argument registers.
+ static const int StackSpaceAllocatedUponFunctionEntry = 1 * RegisterSize; // Registers saved in platformEnterStandardStackFrame below.
+ static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { as->push(JSC::MIPSRegisters::ra); }
+ static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::MIPSRegisters::ra); }
+#endif // Linux on MIPS (32 bit)
+
public: // utility functions
static RegisterInformation getRegisterInfo()
{
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index ee27c21aed..d9615d496f 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -77,7 +77,6 @@ Q_DECLARE_METATYPE(QList<int>)
\ingroup qtjavascript
\inmodule QtQml
- \mainclass
\section1 Evaluating Scripts
@@ -271,7 +270,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
if (val)
obj = val;
if (!obj)
- obj = scope.engine->globalObject();
+ obj = scope.engine->globalObject;
#ifndef QT_NO_TRANSLATION
obj->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
obj->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
@@ -281,7 +280,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
// string prototype extension
- scope.engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"),
+ scope.engine->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"),
QV4::GlobalExtensions::method_string_arg);
#endif
}
@@ -319,7 +318,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
QV4::ExecutionEngine *v4 = d->m_v4Engine;
QV4::Scope scope(v4);
QV4::ScopedContext ctx(scope, v4->currentContext());
- if (ctx->d() != v4->rootContext())
+ if (ctx->d() != v4->rootContext()->d())
ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
@@ -331,7 +330,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
result = script.run();
if (scope.engine->hasException)
result = v4->catchException();
- if (ctx->d() != v4->rootContext())
+ if (ctx->d() != v4->rootContext()->d())
v4->popContext();
return QJSValue(v4, result->asReturnedValue());
}
@@ -414,7 +413,7 @@ QJSValue QJSEngine::globalObject() const
{
Q_D(const QJSEngine);
QV4::Scope scope(d->m_v4Engine);
- QV4::ScopedValue v(scope, d->m_v4Engine->globalObject());
+ QV4::ScopedValue v(scope, d->m_v4Engine->globalObject);
return QJSValue(d->m_v4Engine, v->asReturnedValue());
}
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 50669c46a8..6d0c7cfdda 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -37,13 +37,14 @@
#include "qjsengine.h"
#include "qjsvalue.h"
#include "qjsvalue_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4dateobject_p.h"
#include "qv4runtime_p.h"
#include "qv4variantobject_p.h"
#include "qv4regexpobject_p.h"
+#include "qv4errorobject_p.h"
#include "private/qv8engine_p.h"
#include <private/qv4mm_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -57,7 +58,6 @@
\ingroup qtjavascript
\inmodule QtQml
- \mainclass
QJSValue supports the types defined in the \l{ECMA-262}
standard: The primitive types, which are Undefined, Null, Boolean,
@@ -317,8 +317,7 @@ bool QJSValue::isError() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- Object *o = val->asObject();
- return o && o->asErrorObject();
+ return val->as<ErrorObject>();
}
/*!
@@ -332,7 +331,7 @@ bool QJSValue::isArray() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asArrayObject();
+ return val->as<ArrayObject>();
}
/*!
@@ -349,7 +348,7 @@ bool QJSValue::isObject() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asObject();
+ return val->as<Object>();
}
/*!
@@ -363,7 +362,7 @@ bool QJSValue::isCallable() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asFunctionObject();
+ return val->as<FunctionObject>();
}
/*!
@@ -589,7 +588,7 @@ QVariant QJSValue::toVariant() const
QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
Q_ASSERT(val);
- if (Object *o = val->asObject())
+ if (Object *o = val->as<Object>())
return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
if (val->isString())
@@ -628,7 +627,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -637,7 +636,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
Scope scope(engine);
ScopedCallData callData(scope, args.length());
- callData->thisObject = engine->globalObject()->asReturnedValue();
+ callData->thisObject = engine->globalObject;
for (int i = 0; i < args.size(); ++i) {
if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
@@ -679,7 +678,7 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -733,7 +732,7 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -789,7 +788,7 @@ QJSValue QJSValue::prototype() const
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this)->asObject());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<Object>());
if (!o)
return QJSValue();
ScopedObject p(scope, o->prototype());
@@ -1029,7 +1028,7 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
if (!o)
return QJSValue();
- QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax) : o->getIndexed(arrayIndex));
+ QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax()) : o->getIndexed(arrayIndex));
if (engine->hasException)
engine->catchException();
return QJSValue(engine, result->asReturnedValue());
@@ -1108,7 +1107,7 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
if (arrayIndex != UINT_MAX)
o->putIndexed(arrayIndex, v);
else
- o->put(engine->id_uintMax, v);
+ o->put(engine->id_uintMax(), v);
if (engine->hasException)
engine->catchException();
}
@@ -1224,7 +1223,7 @@ QDateTime QJSValue::toDateTime() const
{
QV4::Value *val = QJSValuePrivate::getValue(this);
if (val) {
- QV4::DateObject *date = val->asDateObject();
+ QV4::DateObject *date = val->as<DateObject>();
if (date)
return date->toQDateTime();
}
@@ -1238,7 +1237,7 @@ QDateTime QJSValue::toDateTime() const
bool QJSValue::isDate() const
{
QV4::Value *val = QJSValuePrivate::getValue(this);
- return val && val->asDateObject();
+ return val && val->as<DateObject>();
}
/*!
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 93a28a4a5f..08dc184412 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -47,7 +47,7 @@
#include <qjsvalue.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4string_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index 1ee4121f5c..a24953ae3f 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -52,9 +52,6 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
QV4::Scope scope(e);
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&v));
iterator.set(e, e->newForEachIteratorObject(o));
-
- currentName = (QV4::String *)0;
- nextName = (QV4::String *)0;
}
@@ -102,8 +99,10 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
}
/*!
@@ -125,7 +124,7 @@ bool QJSValueIterator::hasNext() const
QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return false;
- return !!d_ptr->nextName || d_ptr->nextIndex != UINT_MAX;
+ return d_ptr->nextName.as<QV4::String>() || d_ptr->nextIndex != UINT_MAX;
}
/*!
@@ -143,8 +142,6 @@ bool QJSValueIterator::next()
return false;
d_ptr->currentName = d_ptr->nextName;
d_ptr->currentIndex = d_ptr->nextIndex;
- d_ptr->currentProperty.copy(&d_ptr->nextProperty, d_ptr->nextAttributes);
- d_ptr->currentAttributes = d_ptr->nextAttributes;
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
if (!v4)
@@ -152,9 +149,11 @@ bool QJSValueIterator::next()
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
- return !!d_ptr->currentName || d_ptr->currentIndex != UINT_MAX;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
+ return d_ptr->currentName.as<QV4::String>() || d_ptr->currentIndex != UINT_MAX;
}
/*!
@@ -168,8 +167,8 @@ QString QJSValueIterator::name() const
QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return QString();
- if (!!d_ptr->currentName)
- return d_ptr->currentName->toQString();
+ if (QV4::String *s = d_ptr->currentName.as<QV4::String>())
+ return s->toQString();
if (d_ptr->currentIndex < UINT_MAX)
return QString::number(d_ptr->currentIndex);
return QString();
@@ -192,10 +191,10 @@ QJSValue QJSValueIterator::value() const
if (!obj)
return QJSValue();
- if (!d_ptr->currentName && d_ptr->currentIndex == UINT_MAX)
+ if (!d_ptr->currentName.as<QV4::String>() && d_ptr->currentIndex == UINT_MAX)
return QJSValue();
- QV4::ScopedValue v(scope, obj->getValue(*obj, &d_ptr->currentProperty, d_ptr->currentAttributes));
+ QV4::ScopedValue v(scope, d_ptr->currentIndex == UINT_MAX ? obj->get(d_ptr->currentName.as<QV4::String>()) : obj->getIndexed(d_ptr->currentIndex));
if (scope.hasException()) {
engine->catchException();
return QJSValue();
@@ -214,8 +213,8 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
d_ptr->value = object;
d_ptr->currentIndex = UINT_MAX;
d_ptr->nextIndex = UINT_MAX;
- d_ptr->currentName = (QV4::String *)0;
- d_ptr->nextName = (QV4::String *)0;
+ d_ptr->currentName.clear();
+ d_ptr->nextName.clear();
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
if (!v4) {
d_ptr->iterator.clear();
@@ -228,8 +227,10 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
return *this;
}
diff --git a/src/qml/jsapi/qjsvalueiterator_p.h b/src/qml/jsapi/qjsvalueiterator_p.h
index c17fedf73e..b0d0b2efda 100644
--- a/src/qml/jsapi/qjsvalueiterator_p.h
+++ b/src/qml/jsapi/qjsvalueiterator_p.h
@@ -48,15 +48,9 @@ public:
QJSValue value;
QV4::PersistentValue iterator;
- // ### GC
- QV4::Property currentProperty;
- QV4::PropertyAttributes currentAttributes;
- QV4::StringValue currentName;
+ QV4::PersistentValue currentName;
uint currentIndex;
- // ### GC
- QV4::Property nextProperty;
- QV4::PropertyAttributes nextAttributes;
- QV4::StringValue nextName;
+ QV4::PersistentValue nextName;
uint nextIndex;
};
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index ef44ca6f4d..5ffdebe328 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -10,7 +10,6 @@ SOURCES += \
$$PWD/qv4lookup.cpp \
$$PWD/qv4identifier.cpp \
$$PWD/qv4identifiertable.cpp \
- $$PWD/qv4mm.cpp \
$$PWD/qv4managed.cpp \
$$PWD/qv4internalclass.cpp \
$$PWD/qv4sparsearray.cpp \
@@ -40,7 +39,6 @@ SOURCES += \
$$PWD/qv4sequenceobject.cpp \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
- $$PWD/qv4qmlextensions.cpp \
$$PWD/qv4vme_moth.cpp \
$$PWD/qv4profiling.cpp \
$$PWD/qv4arraybuffer.cpp \
@@ -57,7 +55,6 @@ HEADERS += \
$$PWD/qv4lookup_p.h \
$$PWD/qv4identifier_p.h \
$$PWD/qv4identifiertable_p.h \
- $$PWD/qv4mm_p.h \
$$PWD/qv4managed_p.h \
$$PWD/qv4internalclass_p.h \
$$PWD/qv4sparsearray_p.h \
@@ -90,7 +87,6 @@ HEADERS += \
$$PWD/qv4sequenceobject_p.h \
$$PWD/qv4include_p.h \
$$PWD/qv4qobjectwrapper_p.h \
- $$PWD/qv4qmlextensions_p.h \
$$PWD/qv4vme_moth_p.h \
$$PWD/qv4profiling_p.h \
$$PWD/qv4arraybuffer_p.h \
@@ -102,7 +98,7 @@ HEADERS += \
HEADERS += \
$$PWD/qv4runtime_p.h \
- $$PWD/qv4value_inl_p.h \
+ $$PWD/qv4value_p.h \
$$PWD/qv4string_p.h \
$$PWD/qv4value_p.h
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 92c77570af..55753aec24 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -33,6 +33,7 @@
#include <qv4argumentsobject_p.h>
#include <qv4alloca_p.h>
#include <qv4scopedvalue_p.h>
+#include "qv4string_p.h"
using namespace QV4;
@@ -40,7 +41,7 @@ DEFINE_OBJECT_VTABLE(ArgumentsObject);
Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
: Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass,
- context->d()->engine->objectPrototype.asObject())
+ context->d()->engine->objectPrototype())
, context(context->d())
, fullyCreated(false)
{
@@ -53,21 +54,21 @@ Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
args->setArrayType(Heap::ArrayData::Complex);
if (context->d()->strictMode) {
- Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
- Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller));
- args->propertyAt(CalleePropertyIndex)->value = v4->thrower;
- args->propertyAt(CalleePropertyIndex)->set = v4->thrower;
- args->propertyAt(CallerPropertyIndex)->value = v4->thrower;
- args->propertyAt(CallerPropertyIndex)->set = v4->thrower;
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
+ Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller()));
+ args->propertyAt(CalleePropertyIndex)->value = v4->thrower();
+ args->propertyAt(CalleePropertyIndex)->set = v4->thrower();
+ args->propertyAt(CallerPropertyIndex)->value = v4->thrower();
+ args->propertyAt(CallerPropertyIndex)->set = v4->thrower();
args->arrayReserve(context->argc());
args->arrayPut(0, context->args(), context->argc());
args->d()->fullyCreated = true;
} else {
- Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
args->memberData()->data[CalleePropertyIndex] = context->d()->function->asReturnedValue();
}
- Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length));
+ Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length()));
args->memberData()->data[LengthPropertyIndex] = Primitive::fromInt32(context->d()->callData->argc);
}
@@ -144,9 +145,9 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
return result;
}
-ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
if (args->fullyCreated())
return Object::getIndexed(m, index, hasProperty);
@@ -199,11 +200,11 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
-ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
+ReturnedValue ArgumentsGetterFunction::call(const Managed *getter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsGetterFunction *>(getter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsGetterFunction *>(getter)->engine();
Scope scope(v4);
- Scoped<ArgumentsGetterFunction> g(scope, static_cast<ArgumentsGetterFunction *>(getter));
+ Scoped<ArgumentsGetterFunction> g(scope, static_cast<const ArgumentsGetterFunction *>(getter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
@@ -214,11 +215,11 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
-ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
+ReturnedValue ArgumentsSetterFunction::call(const Managed *setter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsSetterFunction *>(setter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsSetterFunction *>(setter)->engine();
Scope scope(v4);
- Scoped<ArgumentsSetterFunction> s(scope, static_cast<ArgumentsSetterFunction *>(setter));
+ Scoped<ArgumentsSetterFunction> s(scope, static_cast<const ArgumentsSetterFunction *>(setter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 43cd6d1dee..19659429a7 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -59,9 +59,9 @@ struct ArgumentsObject : Object {
CallerPropertyIndex = 3
};
ArgumentsObject(QV4::CallContext *context);
- CallContext *context;
+ Pointer<CallContext> context;
bool fullyCreated;
- MemberData *mappedArguments;
+ Pointer<MemberData> mappedArguments;
};
}
@@ -71,7 +71,7 @@ struct ArgumentsGetterFunction: FunctionObject
V4_OBJECT2(ArgumentsGetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *d);
};
inline
@@ -86,7 +86,7 @@ struct ArgumentsSetterFunction: FunctionObject
V4_OBJECT2(ArgumentsSetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
inline
@@ -111,7 +111,7 @@ struct ArgumentsObject: Object {
}
bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
static bool deleteIndexedProperty(Managed *m, uint index);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 11664f1194..3106d3af23 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -33,6 +33,7 @@
#include "qv4arraybuffer_p.h"
#include "qv4typedarray_p.h"
#include "qv4dataview_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -44,9 +45,9 @@ Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayBufferCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue l(scope, callData->argument(0));
@@ -64,7 +65,7 @@ ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
}
-ReturnedValue ArrayBufferCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayBufferCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -83,7 +84,7 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject())
+ : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
{
data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
@@ -96,7 +97,7 @@ Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
}
Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject())
+ : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
, data(const_cast<QByteArray&>(array).data_ptr())
{
data->ref.ref();
@@ -138,10 +139,10 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1);
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
}
@@ -172,7 +173,7 @@ ReturnedValue ArrayBufferPrototype::method_slice(CallContext *ctx)
double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size);
double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size);
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index fe3150618d..a7f9e92c80 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -61,8 +61,8 @@ struct ArrayBufferCtor: FunctionObject
{
V4_OBJECT2(ArrayBufferCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static ReturnedValue method_isView(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index afcfa00905..627aed0192 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -33,13 +33,14 @@
#include "qv4arraydata_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4runtime_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
-const QV4::ManagedVTable QV4::ArrayData::static_vtbl = {
+const QV4::VTable QV4::ArrayData::static_vtbl = {
0,
QV4::ArrayData::IsExecutionContext,
QV4::ArrayData::IsString,
@@ -230,7 +231,7 @@ ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
bool SimpleArrayData::put(Object *o, uint index, const Value &value)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
// ### honour attributes
dd->data(index) = value;
@@ -244,7 +245,7 @@ bool SimpleArrayData::put(Object *o, uint index, const Value &value)
bool SimpleArrayData::del(Object *o, uint index)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index >= dd->len)
return true;
@@ -266,12 +267,12 @@ void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes att
void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (dd->len + n > dd->alloc) {
realloc(o, Heap::ArrayData::Simple, dd->len + n, false);
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
dd->offset = (dd->offset - n) % dd->alloc;
dd->len += n;
@@ -281,7 +282,7 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SimpleArrayData::pop_front(Object *o)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (!dd->len)
return Encode::undefined();
@@ -294,7 +295,7 @@ ReturnedValue SimpleArrayData::pop_front(Object *o)
uint SimpleArrayData::truncate(Object *o, uint newLen)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (dd->len < newLen)
return newLen;
@@ -318,10 +319,10 @@ uint SimpleArrayData::length(const Heap::ArrayData *d)
bool SimpleArrayData::putArray(Object *o, uint index, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index + n > dd->alloc) {
reallocate(o, index + n + 1, false);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
for (uint i = dd->len; i < index; ++i)
dd->data(i) = Primitive::emptyValue();
@@ -369,13 +370,13 @@ Heap::ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttr
uint SparseArrayData::allocate(Object *o, bool doubleSlot)
{
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse);
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (doubleSlot) {
uint *last = &dd->freeList;
while (1) {
if (*last == UINT_MAX) {
reallocate(o, dd->alloc + 2, true);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
last = &dd->freeList;
Q_ASSERT(*last != UINT_MAX);
}
@@ -393,7 +394,7 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
} else {
if (dd->freeList == UINT_MAX) {
reallocate(o, dd->alloc + 1, false);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
uint idx = dd->freeList;
Q_ASSERT(idx != UINT_MAX);
@@ -418,12 +419,12 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
if (value.isEmpty())
return true;
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
Q_ASSERT(n->value == UINT_MAX || !s->attrs || !s->attrs[n->value].isAccessor());
if (n->value == UINT_MAX)
n->value = allocate(o);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
s->arrayData[n->value] = value;
if (s->attrs)
s->attrs[n->value] = Attr_Data;
@@ -432,7 +433,7 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
bool SparseArrayData::del(Object *o, uint index)
{
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *dd = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = dd->sparse->findNode(index);
if (!n)
@@ -468,28 +469,28 @@ bool SparseArrayData::del(Object *o, uint index)
void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = d->sparse->insert(index);
if (n->value == UINT_MAX) {
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
// need to convert the slot
free(o->arrayData(), n->value);
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
d->attrs[n->value] = attrs;
}
void SparseArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
for (int i = n - 1; i >= 0; --i) {
uint idx = allocate(o);
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
d->arrayData[idx] = values[i];
d->sparse->push_front(idx);
}
@@ -497,7 +498,7 @@ void SparseArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SparseArrayData::pop_front(Object *o)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
uint idx = d->sparse->pop_front();
ReturnedValue v;
@@ -512,7 +513,7 @@ ReturnedValue SparseArrayData::pop_front(Object *o)
uint SparseArrayData::truncate(Object *o, uint newLen)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *begin = d->sparse->lowerBound(newLen);
if (begin != d->sparse->end()) {
SparseArrayNode *it = d->sparse->end()->previousNode();
@@ -606,11 +607,11 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
{
if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) {
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index < 0x1000 || index < d->len + (d->len >> 2)) {
if (index >= d->alloc) {
o->arrayReserve(index + 1);
- d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
if (index >= d->len) {
// mark possible hole in the array
@@ -623,11 +624,11 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
}
o->initSparseArray();
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
return reinterpret_cast<Property *>(s->arrayData + n->value);
}
@@ -737,7 +738,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
if (!arrayData || !arrayData->length())
return;
- if (!(comparefn.isUndefined() || comparefn.asObject())) {
+ if (!(comparefn.isUndefined() || comparefn.as<Object>())) {
engine->throwTypeError();
return;
}
@@ -755,7 +756,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
thisObject->setArrayData(0);
ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
SparseArrayNode *n = sparse->sparse()->begin();
uint i = 0;
@@ -795,7 +796,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
}
} else {
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > d->len)
len = d->len;
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 915e862bbb..667827d1e9 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -47,7 +47,7 @@ namespace QV4 {
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
static const QV4::ArrayVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
const Data *d() const { return static_cast<const Data *>(m); } \
Data *d() { return static_cast<Data *>(m); }
@@ -57,7 +57,7 @@ struct ArrayData;
struct ArrayVTable
{
- ManagedVTable managedVTable;
+ VTable vTable;
uint type;
Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
ReturnedValue (*get)(const Heap::ArrayData *d, uint index);
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 231eb93dd5..25d3d9329b 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -37,6 +37,7 @@
#include "qv4scopedvalue_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -47,9 +48,9 @@ Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArrayCtor *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const ArrayCtor *>(m)->engine();
Scope scope(v4);
ScopedArrayObject a(scope, v4->newArrayObject());
uint len;
@@ -72,7 +73,7 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
return a.asReturnedValue();
}
-ReturnedValue ArrayCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -81,11 +82,11 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isArray"), method_isArray, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
defineDefaultProperty(QStringLiteral("join"), method_join, 1);
@@ -110,7 +111,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx)
{
- bool isArray = ctx->argc() && ctx->args()[0].asArrayObject();
+ bool isArray = ctx->argc() && ctx->args()[0].as<ArrayObject>();
return Encode(isArray);
}
@@ -185,7 +186,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
r4 = arg->toQString();
ScopedObject self(scope, ctx->thisObject());
- ScopedValue length(scope, self->get(ctx->d()->engine->id_length));
+ ScopedValue length(scope, self->get(ctx->d()->engine->id_length()));
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
if (!r2)
@@ -194,7 +195,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
QString R;
// ### FIXME
- if (ArrayObject *a = self->asArrayObject()) {
+ if (ArrayObject *a = self->as<ArrayObject>()) {
ScopedValue e(scope);
for (uint i = 0; i < a->getLength(); ++i) {
if (i)
@@ -242,7 +243,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -256,7 +257,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLength(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -282,7 +283,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
}
double newLen = l + ctx->argc();
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
else {
ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
return ctx->engine()->throwRangeError(str);
@@ -303,7 +304,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len)));
return Encode(len);
}
@@ -354,7 +355,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -388,7 +389,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -523,7 +524,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
}
ctx->d()->strictMode = true;
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
return newArray.asReturnedValue();
}
@@ -561,7 +562,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(newLen);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
return Encode(newLen);
}
@@ -619,7 +620,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
return Encode(-1);
} else {
Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex);
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(instance->d()->arrayData);
+ Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > sa->len)
len = sa->len;
uint idx = fromIndex;
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 4e67eb2e31..422a0de675 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -53,8 +53,8 @@ struct ArrayCtor: FunctionObject
{
V4_OBJECT2(ArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ArrayPrototype: ArrayObject
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 9c293e783b..53f8abf3f2 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4booleanobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -43,14 +44,14 @@ Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
+ReturnedValue BooleanCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<BooleanCtor *>(m)->engine());
+ Scope scope(static_cast<const BooleanCtor *>(m)->engine());
bool n = callData->argc ? callData->args[0].toBoolean() : false;
return Encode(scope.engine->newBooleanObject(n));
}
-ReturnedValue BooleanCtor::call(Managed *, CallData *callData)
+ReturnedValue BooleanCtor::call(const Managed *, CallData *callData)
{
bool value = callData->argc ? callData->args[0].toBoolean() : 0;
return Encode(value);
@@ -60,11 +61,11 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
}
ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
@@ -73,7 +74,7 @@ ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
if (ctx->thisObject().isBoolean()) {
result = ctx->thisObject().booleanValue();
} else {
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
result = thisObject->value();
@@ -87,7 +88,7 @@ ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
if (ctx->thisObject().isBoolean())
return ctx->thisObject().asReturnedValue();
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 903261bdce..77b5a74fde 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -53,8 +53,8 @@ struct BooleanCtor: FunctionObject
{
V4_OBJECT2(BooleanCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct BooleanPrototype: BooleanObject
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 9330f10780..20ed07fa2e 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -36,10 +36,12 @@
#include <qv4context_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include "qv4function_p.h"
#include "qv4errorobject_p.h"
+#include "qv4string_p.h"
+#include "private/qqmlcontextwrapper_p.h"
using namespace QV4;
@@ -48,8 +50,9 @@ DEFINE_MANAGED_VTABLE(CallContext);
DEFINE_MANAGED_VTABLE(WithContext);
DEFINE_MANAGED_VTABLE(CatchContext);
DEFINE_MANAGED_VTABLE(GlobalContext);
+DEFINE_MANAGED_VTABLE(QmlContext);
-Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
+Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *function, CallData *callData)
{
Q_ASSERT(function->function());
@@ -90,31 +93,37 @@ Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName,
return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
}
-Heap::CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
+Heap::QmlContext *ExecutionContext::newQmlContext(QmlContextWrapper *qml)
{
- Scope scope(this);
- Scoped<CallContext> c(scope, d()->engine->memoryManager->allocManaged<CallContext>(requiredMemoryForExecutionContect(f, 0)));
- new (c->d()) Heap::CallContext(d()->engine, qml, f);
- return c->d();
+ return d()->engine->memoryManager->alloc<QmlContext>(this, qml);
}
-
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
Scope scope(this);
// find the right context to create the binding on
- ScopedObject activation(scope, d()->engine->globalObject());
+ ScopedObject activation(scope, d()->engine->globalObject);
ScopedContext ctx(scope, this);
while (ctx) {
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
if (!c->activation)
c->activation = scope.engine->newObject();
activation = c->activation;
break;
}
+ case Heap::ExecutionContext::Type_QmlContext: {
+ Heap::QmlContext *qml = static_cast<Heap::QmlContext *>(ctx->d());
+ activation = qml->qml;
+ break;
+ }
+ default:
+ break;
+ }
ctx = ctx->d()->outer;
}
@@ -130,7 +139,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
: Heap::ExecutionContext(eng, Heap::ExecutionContext::Type_GlobalContext)
{
- global = eng->globalObject()->d();
+ global = eng->globalObject->d();
}
Heap::WithContext::WithContext(ExecutionEngine *engine, QV4::Object *with)
@@ -153,34 +162,23 @@ Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exception
lookups = parent->lookups;
compilationUnit = parent->compilationUnit;
- this->exceptionVarName = exceptionVarName;
+ this->exceptionVarName = exceptionVarName->d();
this->exceptionValue = exceptionValue;
}
-Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_QmlContext)
+Heap::QmlContext::QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml)
+ : Heap::ExecutionContext(outer->engine(), Heap::ExecutionContext::Type_QmlContext)
{
- this->function = function->d();
- callData = reinterpret_cast<CallData *>(this + 1);
- callData->tag = QV4::Value::_Integer_Type;
- callData->argc = 0;
- callData->thisObject = Primitive::undefinedValue();
-
strictMode = false;
- outer = function->scope();
-
- activation = qml->d();
-
- if (function->function()) {
- compilationUnit = function->function()->compilationUnit;
- lookups = compilationUnit->runtimeLookups;
- }
+ callData = parent->callData;
+ this->outer = outer->d();
+ lookups = parent->lookups;
+ compilationUnit = parent->compilationUnit;
- locals = (Value *)(this + 1);
- if (function->varCount())
- std::fill(locals, locals + function->varCount(), Primitive::undefinedValue());
+ this->qml = qml->d();
}
+
Identifier * const *CallContext::formals() const
{
return (d()->function && d()->function->function) ? d()->function->function->internalClass->nameMap.constData() : 0;
@@ -209,16 +207,28 @@ bool ExecutionContext::deleteProperty(String *name)
bool hasWith = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return false;
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
hasWith = true;
ScopedObject withObject(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (withObject->hasProperty(name))
return withObject->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return false;
- } else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ if (global->hasProperty(name))
+ return global->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->needsActivation() || hasWith) {
@@ -227,13 +237,14 @@ bool ExecutionContext::deleteProperty(String *name)
// ### throw in strict mode?
return false;
}
- ScopedObject activation(scope, c->activation);
- if (activation && activation->hasProperty(name))
- return activation->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
- if (global->hasProperty(name))
- return global->deleteProperty(name);
+ ScopedObject qml(scope, c->activation);
+ if (qml && qml->hasProperty(name))
+ return qml->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext:
+ // can't delete properties on qml objects
+ break;
}
}
@@ -254,7 +265,27 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (ctx->outer)
ctx->outer->mark(engine);
- if (ctx->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
+ c->exceptionVarName->mark(engine);
+ c->exceptionValue.mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
+ WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
+ if (w->withObject)
+ w->withObject->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
+ g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_SimpleCallContext:
+ break;
+ case Heap::ExecutionContext::Type_CallContext: {
QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
ctx->callData->thisObject.mark(engine);
for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->function->formalParameterCount()); ++arg)
@@ -264,17 +295,13 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (c->activation)
c->activation->mark(engine);
c->function->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_WithContext) {
- WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
- if (w->withObject)
- w->withObject->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_CatchContext) {
- CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
- c->exceptionVarName->mark(engine);
- c->exceptionValue.mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_GlobalContext) {
- GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
- g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ QmlContext::Data *g = static_cast<QmlContext::Data *>(ctx);
+ g->qml->mark(engine);
+ break;
+ }
}
}
@@ -282,57 +309,71 @@ void ExecutionContext::setProperty(String *name, const Value &value)
{
Scope scope(this);
ScopedContext ctx(scope, this);
+ ScopedObject activation(scope);
+
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ activation = (Object *)0;
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d())) {
+ c->exceptionValue = value;
+ return;
+ }
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (w->hasProperty(name)) {
w->put(name, value);
return;
}
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name)) {
- static_cast<Heap::CatchContext *>(ctx->d())->exceptionValue = value;
- return;
- } else {
- ScopedObject activation(scope, (Object *)0);
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (c->function->function) {
- uint index = c->function->function->internalClass->find(name);
- if (index < UINT_MAX) {
- if (index < c->function->formalParameterCount()) {
- c->callData->args[c->function->formalParameterCount() - index - 1] = value;
- } else {
- index -= c->function->formalParameterCount();
- c->locals[index] = value;
- }
- return;
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ if (c->function->function) {
+ uint index = c->function->function->internalClass->find(name);
+ if (index < UINT_MAX) {
+ if (index < c->function->formalParameterCount()) {
+ c->callData->args[c->function->formalParameterCount() - index - 1] = value;
+ } else {
+ index -= c->function->formalParameterCount();
+ c->locals[index] = value;
}
+ return;
}
- activation = c->activation;
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
}
+ activation = c->activation;
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ activation = static_cast<Heap::QmlContext *>(ctx->d())->qml;
+ activation->put(name, value);
+ return;
+ }
+ }
- if (activation) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext) {
- activation->put(name, value);
- return;
- } else {
- uint member = activation->internalClass()->find(name);
- if (member < UINT_MAX) {
- activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
- return;
- }
- }
+ if (activation) {
+ uint member = activation->internalClass()->find(name);
+ if (member < UINT_MAX) {
+ activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
+ return;
}
}
}
- if (d()->strictMode || name->equals(d()->engine->id_this)) {
+
+ if (d()->strictMode || name->equals(d()->engine->id_this())) {
ScopedValue n(scope, name->asReturnedValue());
engine()->throwReferenceError(n);
return;
}
- d()->engine->globalObject()->put(name, value);
+ d()->engine->globalObject->put(name, value);
}
ReturnedValue ExecutionContext::getProperty(String *name)
@@ -341,14 +382,22 @@ ReturnedValue ExecutionContext::getProperty(String *name)
ScopedValue v(scope);
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
@@ -356,17 +405,18 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (hasProperty) {
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
@@ -387,14 +437,16 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
+ v = qml->get(name, &hasProperty);
if (hasProperty)
return v->asReturnedValue();
+ break;
+ }
}
}
ScopedValue n(scope, name);
@@ -408,14 +460,22 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object **
*base = (Heap::Object *)0;
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
@@ -424,48 +484,50 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object **
*base = w->d();
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < f->formalParameterCount())
- return c->callData->args[f->formalParameterCount() - index - 1].asReturnedValue();
- return c->locals[index - f->formalParameterCount()].asReturnedValue();
+ if (index < c->function->formalParameterCount())
+ return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
+ return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
}
}
ScopedObject activation(scope, c->activation);
if (activation) {
bool hasProperty = false;
v = activation->get(name, &hasProperty);
- if (hasProperty) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext)
- *base = activation->d();
+ if (hasProperty)
return v->asReturnedValue();
- }
}
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
- return c->function->asReturnedValue();
+ return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
- if (hasProperty)
+ v = qml->get(name, &hasProperty);
+ if (hasProperty) {
+ *base = qml->d();
return v->asReturnedValue();
+ }
+ break;
+ }
}
}
ScopedValue n(scope, name);
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 8392dd836d..8eda4ed12c 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -45,6 +45,8 @@ struct CompilationUnit;
struct Function;
}
+struct QmlContextWrapper;
+struct Identifier;
struct CallContext;
struct CatchContext;
struct WithContext;
@@ -74,9 +76,9 @@ struct ExecutionContext : Base {
Type_GlobalContext = 0x1,
Type_CatchContext = 0x2,
Type_WithContext = 0x3,
- Type_SimpleCallContext = 0x4,
- Type_CallContext = 0x5,
- Type_QmlContext = 0x6
+ Type_QmlContext = 0x4,
+ Type_SimpleCallContext = 0x5,
+ Type_CallContext = 0x6
};
inline ExecutionContext(ExecutionEngine *engine, ContextType t);
@@ -84,8 +86,8 @@ struct ExecutionContext : Base {
CallData *callData;
ExecutionEngine *engine;
- ExecutionContext *parent;
- ExecutionContext *outer;
+ Pointer<ExecutionContext> parent;
+ Pointer<ExecutionContext> outer;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
@@ -102,29 +104,34 @@ struct CallContext : ExecutionContext {
locals = 0;
activation = 0;
}
- CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function);
- FunctionObject *function;
+ Pointer<FunctionObject> function;
Value *locals;
- Object *activation;
+ Pointer<Object> activation;
};
struct GlobalContext : ExecutionContext {
GlobalContext(ExecutionEngine *engine);
- Object *global;
+ Pointer<Object> global;
};
struct CatchContext : ExecutionContext {
CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue);
- StringValue exceptionVarName;
+ Pointer<String> exceptionVarName;
Value exceptionValue;
};
struct WithContext : ExecutionContext {
WithContext(ExecutionEngine *engine, QV4::Object *with);
- Object *withObject;
+ Pointer<Object> withObject;
};
+struct QmlContextWrapper;
+
+struct QmlContext : ExecutionContext {
+ QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml);
+ Pointer<QmlContextWrapper> qml;
+};
}
@@ -139,10 +146,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
- Heap::CallContext *newCallContext(FunctionObject *f, CallData *callData);
+ Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
Heap::WithContext *newWithContext(Object *with);
Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue);
- Heap::CallContext *newQmlContext(FunctionObject *f, Object *qml);
+ Heap::QmlContext *newQmlContext(QmlContextWrapper *qml);
void createMutableBinding(String *name, bool deletable);
@@ -160,7 +167,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
static void markObjects(Heap::Base *m, ExecutionEngine *e);
- const Value &thisObject() const {
+ Value &thisObject() const {
return d()->callData->thisObject;
}
int argc() const {
@@ -208,6 +215,11 @@ struct WithContext : public ExecutionContext
V4_MANAGED(WithContext, ExecutionContext)
};
+struct QmlContext : public ExecutionContext
+{
+ V4_MANAGED(QmlContext, ExecutionContext)
+};
+
inline CallContext *ExecutionContext::asCallContext()
{
return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index 8a66c2cbfc..a741d61d10 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -33,6 +33,7 @@
#include "qv4dataview_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include "qendian.h"
@@ -46,9 +47,9 @@ Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DataViewCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
Scoped<ArrayBuffer> buffer(scope, callData->argument(0));
if (!buffer)
return scope.engine->throwTypeError();
@@ -69,14 +70,14 @@ ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
}
-ReturnedValue DataViewCtor::call(Managed *that, CallData *callData)
+ReturnedValue DataViewCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
Heap::DataView::DataView(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->dataViewPrototype.asObject()),
+ : Heap::Object(e->emptyClass, e->dataViewPrototype()),
buffer(0),
byteLength(0),
byteOffset(0)
@@ -94,9 +95,9 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index 3f0c1e9e23..e98239396a 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -48,7 +48,7 @@ struct DataViewCtor : FunctionObject {
struct DataView : Object {
DataView(ExecutionEngine *e);
- ArrayBuffer *buffer;
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
};
@@ -59,8 +59,8 @@ struct DataViewCtor: FunctionObject
{
V4_OBJECT2(DataViewCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct DataView : Object
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 451ef2486d..3f45751695 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -36,6 +36,7 @@
#include "qv4objectproto_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDebug>
#include <QtCore/QDateTime>
@@ -628,14 +629,14 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date)
- : Heap::Object(engine->emptyClass, engine->datePrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->datePrototype())
{
- value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
+ this->date = date.isValid() ? date.toMSecsSinceEpoch() : qSNaN();
}
QDateTime DateObject::toQDateTime() const
{
- return ToDateTime(date().asDouble(), Qt::LocalTime);
+ return ToDateTime(date(), Qt::LocalTime);
}
DEFINE_OBJECT_VTABLE(DateCtor);
@@ -645,9 +646,9 @@ Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DateCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<DateCtor *>(m)->engine());
+ Scope scope(static_cast<const DateCtor *>(m)->engine());
double t = 0;
if (callData->argc == 0)
@@ -655,15 +656,16 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
else if (callData->argc == 1) {
ScopedValue arg(scope, callData->args[0]);
- if (DateObject *d = arg->asDateObject())
- arg = d->date();
- else
+ if (DateObject *d = arg->as<DateObject>()) {
+ t = d->date();
+ } else {
arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT);
- if (arg->isString())
- t = ParseString(arg->stringValue()->toQString());
- else
- t = TimeClip(arg->toNumber());
+ if (arg->isString())
+ t = ParseString(arg->stringValue()->toQString());
+ else
+ t = TimeClip(arg->toNumber());
+ }
}
else { // d.argc > 1
@@ -683,18 +685,18 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
return Encode(scope.engine->newDateObject(Primitive::fromDouble(t)));
}
-ReturnedValue DateCtor::call(Managed *m, CallData *)
+ReturnedValue DateCtor::call(const Managed *m, CallData *)
{
double t = currentTime();
- return static_cast<DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
+ return static_cast<const DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
}
void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(7));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(7));
LocalTZA = getLocalTZA();
ctor->defineDefaultProperty(QStringLiteral("parse"), method_parse, 1);
@@ -702,13 +704,13 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("now"), method_now, 0);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toDateString"), method_toDateString, 0);
defineDefaultProperty(QStringLiteral("toTimeString"), method_toTimeString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString, 0);
defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString, 0);
- defineDefaultProperty(engine->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("getTime"), method_getTime, 0);
defineDefaultProperty(QStringLiteral("getYear"), method_getYear, 0);
defineDefaultProperty(QStringLiteral("getFullYear"), method_getFullYear, 0);
@@ -752,8 +754,8 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
double DatePrototype::getThisDate(ExecutionContext *ctx)
{
- if (DateObject *thisObject = ctx->thisObject().asDateObject())
- return thisObject->date().asDouble();
+ if (DateObject *thisObject = ctx->thisObject().as<DateObject>())
+ return thisObject->date();
else {
ctx->engine()->throwTypeError();
return 0;
@@ -994,8 +996,8 @@ ReturnedValue DatePrototype::method_setTime(CallContext *ctx)
return ctx->engine()->throwTypeError();
double t = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(t));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(t));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
@@ -1005,175 +1007,175 @@ ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (std::isnan(t))
t = 0;
else
@@ -1189,49 +1191,49 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
r = UTC(MakeDate(r, TimeWithinDay(t)));
r = TimeClip(r);
}
- self->date().setDouble(r);
- return self->date().asReturnedValue();
+ self->setDate(r);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
if (std::isnan(t))
t = 0;
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue();
}
@@ -1250,11 +1252,11 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits)
ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (!std::isfinite(t))
return ctx->engine()->throwRangeError(ctx->thisObject());
@@ -1297,7 +1299,7 @@ ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
ScopedValue v(scope, O->objectValue()->get(s));
- FunctionObject *toIso = v->asFunctionObject();
+ FunctionObject *toIso = v->as<FunctionObject>();
if (!toIso)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index dad3689054..133a8d27e8 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -49,18 +49,19 @@ struct DateObject : Object {
DateObject(InternalClass *ic, QV4::Object *prototype)
: Object(ic, prototype)
{
- value = Encode(qSNaN());
+ date = qSNaN();
}
DateObject(QV4::ExecutionEngine *engine, const Value &date)
- : Object(engine->emptyClass, engine->datePrototype.asObject())
+ : Object(engine->emptyClass, engine->datePrototype())
{
- value = date;
+ this->date = date.toNumber();
}
DateObject(QV4::ExecutionEngine *engine, const QDateTime &date);
- Value value;
+ double date;
};
+
struct DateCtor : FunctionObject {
DateCtor(QV4::ExecutionContext *scope);
};
@@ -72,19 +73,23 @@ struct DateObject: Object {
Q_MANAGED_TYPE(DateObject)
- Value date() const { return d()->value; }
- Value &date() { return d()->value; }
- void setDate(const Value &date) { d()->value = date; }
+ double date() const { return d()->date; }
+ void setDate(double date) { d()->date = date; }
QDateTime toQDateTime() const;
};
+template<>
+inline const DateObject *Value::as() const {
+ return isManaged() && m && m->vtable->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : 0;
+}
+
struct DateCtor: FunctionObject
{
V4_OBJECT2(DateCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *);
};
struct DatePrototype: DateObject
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 36e7a3558c..7bd5d49f3c 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -40,6 +40,7 @@
#include "qv4script_p.h"
#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
+#include "qv4string_p.h"
#include <iostream>
#include <algorithm>
@@ -469,7 +470,7 @@ void Debugger::collectThrownValue(Collector *collector)
void run()
{
Scope scope(engine);
- ScopedValue v(scope, engine->exceptionValue);
+ ScopedValue v(scope, *engine->exceptionValue);
collector->collect(QStringLiteral("exception"), v);
}
};
@@ -497,7 +498,7 @@ QVector<Heap::ExecutionContext::ContextType> Debugger::getScopeTypes(int frame)
Scope scope(m_engine);
Scoped<CallContext> sctxt(scope, findContext(m_engine->currentContext(), frame));
- if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_SimpleCallContext)
+ if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_QmlContext)
return types;
ScopedContext it(scope, sctxt->d());
@@ -793,7 +794,7 @@ void Debugger::Collector::collect(const QString &name, const ScopedValue &value)
addBoolean(name, value->booleanValue());
break;
case Value::Managed_Type:
- if (String *s = value->asString())
+ if (const String *s = value->as<String>())
addString(name, s->toQString());
else
addObject(name, value);
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index ba6f5a3b79..016187f488 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4context_p.h>
-#include <qv4value_inl_p.h>
+#include <qv4value_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
@@ -48,7 +48,7 @@
#include <qv4regexp_p.h>
#include <qv4variantobject_p.h>
#include <qv4runtime_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include <qv4dateobject_p.h>
#include <qv4jsonobject_p.h>
@@ -59,7 +59,6 @@
#include "qv4executableallocator_p.h"
#include "qv4sequenceobject_p.h"
#include "qv4qobjectwrapper_p.h"
-#include "qv4qmlextensions_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraybuffer_p.h"
#include "qv4dataview_p.h"
@@ -192,6 +191,7 @@ QQmlEngine *ExecutionEngine::qmlEngine() const
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
: current(0)
+ , hasException(false)
, memoryManager(new QV4::MemoryManager(this))
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -206,13 +206,9 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
- , m_qmlExtensions(0)
{
MemoryManager::GCBlocker gcBlocker(memoryManager);
- exceptionValue = Encode::undefined();
- hasException = false;
-
if (!factory) {
#ifdef V4_ENABLE_JIT
@@ -236,6 +232,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
jsStackBase = (Value *)jsStack->base();
jsStackTop = jsStackBase;
+ exceptionValue = jsAlloca(1);
+ globalObject = static_cast<Object *>(jsAlloca(1));
+ jsObjects = jsAlloca(NJSObjects);
+ typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes));
+ typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
+ jsStrings = jsAlloca(NJSStrings);
+
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
#endif
@@ -246,208 +249,208 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
if (!recheckCStackLimits())
qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize);
- Scope scope(this);
-
identifierTable = new IdentifierTable(this);
classPool = new InternalClassPool;
emptyClass = new (classPool) InternalClass(this);
- id_empty = newIdentifier(QString());
- id_undefined = newIdentifier(QStringLiteral("undefined"));
- id_null = newIdentifier(QStringLiteral("null"));
- id_true = newIdentifier(QStringLiteral("true"));
- id_false = newIdentifier(QStringLiteral("false"));
- id_boolean = newIdentifier(QStringLiteral("boolean"));
- id_number = newIdentifier(QStringLiteral("number"));
- id_string = newIdentifier(QStringLiteral("string"));
- id_object = newIdentifier(QStringLiteral("object"));
- id_function = newIdentifier(QStringLiteral("function"));
- id_length = newIdentifier(QStringLiteral("length"));
- id_prototype = newIdentifier(QStringLiteral("prototype"));
- id_constructor = newIdentifier(QStringLiteral("constructor"));
- id_arguments = newIdentifier(QStringLiteral("arguments"));
- id_caller = newIdentifier(QStringLiteral("caller"));
- id_callee = newIdentifier(QStringLiteral("callee"));
- id_this = newIdentifier(QStringLiteral("this"));
- id___proto__ = newIdentifier(QStringLiteral("__proto__"));
- id_enumerable = newIdentifier(QStringLiteral("enumerable"));
- id_configurable = newIdentifier(QStringLiteral("configurable"));
- id_writable = newIdentifier(QStringLiteral("writable"));
- id_value = newIdentifier(QStringLiteral("value"));
- id_get = newIdentifier(QStringLiteral("get"));
- id_set = newIdentifier(QStringLiteral("set"));
- id_eval = newIdentifier(QStringLiteral("eval"));
- id_uintMax = newIdentifier(QStringLiteral("4294967295"));
- id_name = newIdentifier(QStringLiteral("name"));
- id_index = newIdentifier(QStringLiteral("index"));
- id_input = newIdentifier(QStringLiteral("input"));
- id_toString = newIdentifier(QStringLiteral("toString"));
- id_destroy = newIdentifier(QStringLiteral("destroy"));
- id_valueOf = newIdentifier(QStringLiteral("valueOf"));
- id_byteLength = newIdentifier(QStringLiteral("byteLength"));
- id_byteOffset = newIdentifier(QStringLiteral("byteOffset"));
- id_buffer = newIdentifier(QStringLiteral("buffer"));
- id_lastIndex = newIdentifier(QStringLiteral("lastIndex"));
-
- objectPrototype = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
-
- arrayClass = emptyClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
- arrayPrototype = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype.asObject());
-
- InternalClass *argsClass = emptyClass->addMember(id_length, Attr_NotEnumerable);
- argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
- strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-
- m_globalObject = newObject();
- Q_ASSERT(globalObject()->d()->vtable);
+ jsStrings[String_Empty] = newIdentifier(QString());
+ jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined"));
+ jsStrings[String_null] = newIdentifier(QStringLiteral("null"));
+ jsStrings[String_true] = newIdentifier(QStringLiteral("true"));
+ jsStrings[String_false] = newIdentifier(QStringLiteral("false"));
+ jsStrings[String_boolean] = newIdentifier(QStringLiteral("boolean"));
+ jsStrings[String_number] = newIdentifier(QStringLiteral("number"));
+ jsStrings[String_string] = newIdentifier(QStringLiteral("string"));
+ jsStrings[String_object] = newIdentifier(QStringLiteral("object"));
+ jsStrings[String_function] = newIdentifier(QStringLiteral("function"));
+ jsStrings[String_length] = newIdentifier(QStringLiteral("length"));
+ jsStrings[String_prototype] = newIdentifier(QStringLiteral("prototype"));
+ jsStrings[String_constructor] = newIdentifier(QStringLiteral("constructor"));
+ jsStrings[String_arguments] = newIdentifier(QStringLiteral("arguments"));
+ jsStrings[String_caller] = newIdentifier(QStringLiteral("caller"));
+ jsStrings[String_callee] = newIdentifier(QStringLiteral("callee"));
+ jsStrings[String_this] = newIdentifier(QStringLiteral("this"));
+ jsStrings[String___proto__] = newIdentifier(QStringLiteral("__proto__"));
+ jsStrings[String_enumerable] = newIdentifier(QStringLiteral("enumerable"));
+ jsStrings[String_configurable] = newIdentifier(QStringLiteral("configurable"));
+ jsStrings[String_writable] = newIdentifier(QStringLiteral("writable"));
+ jsStrings[String_value] = newIdentifier(QStringLiteral("value"));
+ jsStrings[String_get] = newIdentifier(QStringLiteral("get"));
+ jsStrings[String_set] = newIdentifier(QStringLiteral("set"));
+ jsStrings[String_eval] = newIdentifier(QStringLiteral("eval"));
+ jsStrings[String_uintMax] = newIdentifier(QStringLiteral("4294967295"));
+ jsStrings[String_name] = newIdentifier(QStringLiteral("name"));
+ jsStrings[String_index] = newIdentifier(QStringLiteral("index"));
+ jsStrings[String_input] = newIdentifier(QStringLiteral("input"));
+ jsStrings[String_toString] = newIdentifier(QStringLiteral("toString"));
+ jsStrings[String_destroy] = newIdentifier(QStringLiteral("destroy"));
+ jsStrings[String_valueOf] = newIdentifier(QStringLiteral("valueOf"));
+ jsStrings[String_byteLength] = newIdentifier(QStringLiteral("byteLength"));
+ jsStrings[String_byteOffset] = newIdentifier(QStringLiteral("byteOffset"));
+ jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
+ jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
+
+ jsObjects[ObjectProto] = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
+
+ arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
+ jsObjects[ArrayProto] = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype());
+
+ InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable);
+ argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable);
+ strictArgumentsObjectClass = argsClass->addMember(id_callee(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+
+ *static_cast<Value *>(globalObject) = newObject();
+ Q_ASSERT(globalObject->d()->vtable);
initRootContext();
- stringPrototype = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype.asObject());
- numberPrototype = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype.asObject());
- booleanPrototype = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype.asObject());
- datePrototype = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype.asObject());
+ jsObjects[StringProto] = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype());
+ jsObjects[NumberProto] = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype());
+ jsObjects[BooleanProto] = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype());
+ jsObjects[DateProto] = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype());
uint index;
- InternalClass *functionProtoClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable, &index);
+ InternalClass *functionProtoClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject());
- functionClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ jsObjects[FunctionProto] = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype());
+ functionClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- simpleScriptFunctionClass = functionClass->addMember(id_name, Attr_ReadOnly, &index);
+ simpleScriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name);
- simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length, Attr_ReadOnly, &index);
+ simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length);
- protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index);
+ protoClass = emptyClass->addMember(id_constructor(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- regExpPrototype = memoryManager->alloc<RegExpPrototype>(this);
- regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
+ jsObjects[RegExpProto] = memoryManager->alloc<RegExpPrototype>(this);
+ regExpExecArrayClass = arrayClass->addMember(id_index(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
- regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
+ regExpExecArrayClass = regExpExecArrayClass->addMember(id_input(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- errorPrototype = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype.asObject());
- evalErrorPrototype = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype.asObject());
- rangeErrorPrototype = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype.asObject());
- referenceErrorPrototype = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype.asObject());
- syntaxErrorPrototype = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype.asObject());
- typeErrorPrototype = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype.asObject());
- uRIErrorPrototype = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype.asObject());
+ jsObjects[ErrorProto] = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype());
+ jsObjects[EvalErrorProto] = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype());
+ jsObjects[RangeErrorProto] = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype());
+ jsObjects[ReferenceErrorProto] = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype());
+ jsObjects[SyntaxErrorProto] = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype());
+ jsObjects[TypeErrorProto] = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype());
+ jsObjects[URIErrorProto] = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype());
- variantPrototype = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype.asObject());
- Q_ASSERT(variantPrototype.asObject()->prototype() == objectPrototype.asObject()->d());
+ jsObjects[VariantProto] = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype());
+ Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d());
- sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype.asObject()));
+ Scope scope(this);
+ jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype()));
ScopedContext global(scope, rootContext());
- objectCtor = memoryManager->alloc<ObjectCtor>(global);
- stringCtor = memoryManager->alloc<StringCtor>(global);
- numberCtor = memoryManager->alloc<NumberCtor>(global);
- booleanCtor = memoryManager->alloc<BooleanCtor>(global);
- arrayCtor = memoryManager->alloc<ArrayCtor>(global);
- functionCtor = memoryManager->alloc<FunctionCtor>(global);
- dateCtor = memoryManager->alloc<DateCtor>(global);
- regExpCtor = memoryManager->alloc<RegExpCtor>(global);
- errorCtor = memoryManager->alloc<ErrorCtor>(global);
- evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(global);
- rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(global);
- referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(global);
- syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(global);
- typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(global);
- uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(global);
-
- static_cast<ObjectPrototype *>(objectPrototype.asObject())->init(this, objectCtor.asObject());
- static_cast<StringPrototype *>(stringPrototype.asObject())->init(this, stringCtor.asObject());
- static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject());
- static_cast<BooleanPrototype *>(booleanPrototype.asObject())->init(this, booleanCtor.asObject());
- static_cast<ArrayPrototype *>(arrayPrototype.asObject())->init(this, arrayCtor.asObject());
- static_cast<DatePrototype *>(datePrototype.asObject())->init(this, dateCtor.asObject());
- static_cast<FunctionPrototype *>(functionPrototype.asObject())->init(this, functionCtor.asObject());
- static_cast<RegExpPrototype *>(regExpPrototype.asObject())->init(this, regExpCtor.asObject());
- static_cast<ErrorPrototype *>(errorPrototype.asObject())->init(this, errorCtor.asObject());
- static_cast<EvalErrorPrototype *>(evalErrorPrototype.asObject())->init(this, evalErrorCtor.asObject());
- static_cast<RangeErrorPrototype *>(rangeErrorPrototype.asObject())->init(this, rangeErrorCtor.asObject());
- static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.asObject())->init(this, referenceErrorCtor.asObject());
- static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.asObject())->init(this, syntaxErrorCtor.asObject());
- static_cast<TypeErrorPrototype *>(typeErrorPrototype.asObject())->init(this, typeErrorCtor.asObject());
- static_cast<URIErrorPrototype *>(uRIErrorPrototype.asObject())->init(this, uRIErrorCtor.asObject());
-
- static_cast<VariantPrototype *>(variantPrototype.asObject())->init();
- sequencePrototype.cast<SequencePrototype>()->init();
+ jsObjects[Object_Ctor] = memoryManager->alloc<ObjectCtor>(global);
+ jsObjects[String_Ctor] = memoryManager->alloc<StringCtor>(global);
+ jsObjects[Number_Ctor] = memoryManager->alloc<NumberCtor>(global);
+ jsObjects[Boolean_Ctor] = memoryManager->alloc<BooleanCtor>(global);
+ jsObjects[Array_Ctor] = memoryManager->alloc<ArrayCtor>(global);
+ jsObjects[Function_Ctor] = memoryManager->alloc<FunctionCtor>(global);
+ jsObjects[Date_Ctor] = memoryManager->alloc<DateCtor>(global);
+ jsObjects[RegExp_Ctor] = memoryManager->alloc<RegExpCtor>(global);
+ jsObjects[Error_Ctor] = memoryManager->alloc<ErrorCtor>(global);
+ jsObjects[EvalError_Ctor] = memoryManager->alloc<EvalErrorCtor>(global);
+ jsObjects[RangeError_Ctor] = memoryManager->alloc<RangeErrorCtor>(global);
+ jsObjects[ReferenceError_Ctor] = memoryManager->alloc<ReferenceErrorCtor>(global);
+ jsObjects[SyntaxError_Ctor] = memoryManager->alloc<SyntaxErrorCtor>(global);
+ jsObjects[TypeError_Ctor] = memoryManager->alloc<TypeErrorCtor>(global);
+ jsObjects[URIError_Ctor] = memoryManager->alloc<URIErrorCtor>(global);
+
+ static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
+ static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
+ static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
+ static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
+ static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
+ static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
+ static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
+ static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
+ static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
+ static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
+ static_cast<RangeErrorPrototype *>(rangeErrorPrototype())->init(this, rangeErrorCtor());
+ static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype())->init(this, referenceErrorCtor());
+ static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor());
+ static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
+ static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
+
+ static_cast<VariantPrototype *>(variantPrototype())->init();
+ sequencePrototype()->cast<SequencePrototype>()->init();
// typed arrays
- arrayBufferCtor = memoryManager->alloc<ArrayBufferCtor>(global);
- arrayBufferPrototype = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<ArrayBufferPrototype *>(arrayBufferPrototype.asObject())->init(this, arrayBufferCtor.asObject());
+ jsObjects[ArrayBuffer_Ctor] = memoryManager->alloc<ArrayBufferCtor>(global);
+ jsObjects[ArrayBufferProto] = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype());
+ static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
- dataViewCtor = memoryManager->alloc<DataViewCtor>(global);
- dataViewPrototype = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<DataViewPrototype *>(dataViewPrototype.asObject())->init(this, dataViewCtor.asObject());
+ jsObjects[DataView_Ctor] = memoryManager->alloc<DataViewCtor>(global);
+ jsObjects[DataViewProto] = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype());
+ static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
+ jsObjects[ValueTypeProto] = (Heap::Base *) 0;
for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
- typedArrayCtors[i] = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
- typedArrayPrototype[i] = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
- typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject()));
+ static_cast<Value &>(typedArrayCtors[i]) = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
+ typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
}
//
// set up the global object
//
- rootContext()->global = globalObject()->d();
- rootContext()->callData->thisObject = globalObject();
- Q_ASSERT(globalObject()->d()->vtable);
-
- globalObject()->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("String"), stringCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Number"), numberCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Array"), arrayCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Function"), functionCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Date"), dateCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Error"), errorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
-
- globalObject()->defineDefaultProperty(QStringLiteral("ArrayBuffer"), arrayBufferCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("DataView"), dataViewCtor);
+ rootContext()->d()->global = globalObject->d();
+ rootContext()->d()->callData->thisObject = globalObject;
+ Q_ASSERT(globalObject->d()->vtable);
+
+ globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Array"), *arrayCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Function"), *functionCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Date"), *dateCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RegExp"), *regExpCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Error"), *errorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("EvalError"), *evalErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RangeError"), *rangeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), *referenceErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), *syntaxErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor());
+
+ globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor());
ScopedString str(scope);
for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- globalObject()->defineDefaultProperty((str = typedArrayCtors[i].asFunctionObject()->name())->toQString(), typedArrayCtors[i]);
+ globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]);
ScopedObject o(scope);
- globalObject()->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this)));
- globalObject()->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this)));
+ globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this)));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this)));
- globalObject()->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
- globalObject()->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
- globalObject()->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
+ globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
+ globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
+ globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
- evalFunction = memoryManager->alloc<EvalFunction>(global);
- globalObject()->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction));
+ jsObjects[Eval_Function] = memoryManager->alloc<EvalFunction>(global);
+ globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
- globalObject()->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
- globalObject()->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
+ globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
ScopedString name(scope, newString(QStringLiteral("thrower")));
- thrower = BuiltinFunction::create(global, name, ::throwTypeError);
+ jsObjects[ThrowerObject] = BuiltinFunction::create(global, name, ::throwTypeError);
}
ExecutionEngine::~ExecutionEngine()
@@ -466,7 +469,6 @@ ExecutionEngine::~ExecutionEngine()
foreach (QV4::CompiledData::CompilationUnit *unit, remainingUnits)
unit->unlink();
- delete m_qmlExtensions;
emptyClass->destroy();
delete classPool;
delete bumperPointerAllocator;
@@ -499,10 +501,10 @@ void ExecutionEngine::initRootContext()
r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1);
r->d()->callData->tag = QV4::Value::_Integer_Type;
r->d()->callData->argc = 0;
- r->d()->callData->thisObject = globalObject();
+ r->d()->callData->thisObject = globalObject;
r->d()->callData->args[0] = Encode::undefined();
- m_rootContext = r->d();
+ jsObjects[RootContect] = r;
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -514,7 +516,7 @@ Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
{
Scope scope(this);
Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
- g->d()->callData = rootContext()->callData;
+ g->d()->callData = rootContext()->d()->callData;
Q_ASSERT(currentContext() == g->d());
return g->d();
@@ -546,10 +548,10 @@ Heap::String *ExecutionEngine::newIdentifier(const QString &text)
return identifierTable->insertString(text);
}
-Heap::Object *ExecutionEngine::newStringObject(const Value &value)
+Heap::Object *ExecutionEngine::newStringObject(const String *string)
{
Scope scope(this);
- Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, value));
+ Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, string));
return object->d();
}
@@ -648,7 +650,7 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype.asObject(), value));
+ ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype(), value));
return object->d();
}
@@ -718,7 +720,7 @@ Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
return obj->d();
}
-Heap::Object *ExecutionEngine::qmlContextObject() const
+Heap::QmlContextWrapper *ExecutionEngine::qmlContextObject() const
{
Heap::ExecutionContext *ctx = currentContext();
@@ -735,8 +737,20 @@ Heap::Object *ExecutionEngine::qmlContextObject() const
if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
return 0;
- Q_ASSERT(static_cast<Heap::CallContext *>(ctx)->activation);
- return static_cast<Heap::CallContext *>(ctx)->activation;
+ Q_ASSERT(static_cast<Heap::QmlContext *>(ctx)->qml);
+ return static_cast<Heap::QmlContext *>(ctx)->qml;
+}
+
+QObject *ExecutionEngine::qmlScopeObject() const
+{
+ return qmlContextObject()->scopeObject;
+}
+
+QQmlContextData *ExecutionEngine::callingQmlContext() const
+{
+ Heap::QmlContextWrapper *w = qmlContextObject();
+
+ return w ? w->context.contextData() : 0;
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -772,7 +786,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
StackFrame frame;
frame.source = globalCode->sourceFile();
frame.function = globalCode->name()->toQString();
- frame.line = rootContext()->lineNumber;
+ frame.line = rootContext()->d()->lineNumber;
frame.column = -1;
stack.append(frame);
@@ -884,8 +898,6 @@ void ExecutionEngine::markObjects()
{
identifierTable->mark(this);
- globalObject()->mark(this);
-
for (int i = 0; i < nArgumentsAccessors; ++i) {
const Property &pd = argumentsAccessors[i];
if (Heap::FunctionObject *getter = pd.getter())
@@ -904,93 +916,6 @@ void ExecutionEngine::markObjects()
c = c->parent;
}
- id_empty->mark(this);
- id_undefined->mark(this);
- id_null->mark(this);
- id_true->mark(this);
- id_false->mark(this);
- id_boolean->mark(this);
- id_number->mark(this);
- id_string->mark(this);
- id_object->mark(this);
- id_function->mark(this);
- id_length->mark(this);
- id_prototype->mark(this);
- id_constructor->mark(this);
- id_arguments->mark(this);
- id_caller->mark(this);
- id_callee->mark(this);
- id_this->mark(this);
- id___proto__->mark(this);
- id_enumerable->mark(this);
- id_configurable->mark(this);
- id_writable->mark(this);
- id_value->mark(this);
- id_get->mark(this);
- id_set->mark(this);
- id_eval->mark(this);
- id_uintMax->mark(this);
- id_name->mark(this);
- id_index->mark(this);
- id_input->mark(this);
- id_toString->mark(this);
- id_destroy->mark(this);
- id_valueOf->mark(this);
- id_byteLength->mark(this);
- id_byteOffset->mark(this);
- id_buffer->mark(this);
- id_lastIndex->mark(this);
-
- objectCtor.mark(this);
- stringCtor.mark(this);
- numberCtor.mark(this);
- booleanCtor.mark(this);
- arrayCtor.mark(this);
- functionCtor.mark(this);
- dateCtor.mark(this);
- regExpCtor.mark(this);
- errorCtor.mark(this);
- evalErrorCtor.mark(this);
- rangeErrorCtor.mark(this);
- referenceErrorCtor.mark(this);
- syntaxErrorCtor.mark(this);
- typeErrorCtor.mark(this);
- uRIErrorCtor.mark(this);
- arrayBufferCtor.mark(this);
- dataViewCtor.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayCtors[i].mark(this);
-
- objectPrototype.mark(this);
- arrayPrototype.mark(this);
- stringPrototype.mark(this);
- numberPrototype.mark(this);
- booleanPrototype.mark(this);
- datePrototype.mark(this);
- functionPrototype.mark(this);
- regExpPrototype.mark(this);
- errorPrototype.mark(this);
- evalErrorPrototype.mark(this);
- rangeErrorPrototype.mark(this);
- referenceErrorPrototype.mark(this);
- syntaxErrorPrototype.mark(this);
- typeErrorPrototype.mark(this);
- uRIErrorPrototype.mark(this);
- variantPrototype.mark(this);
- sequencePrototype.mark(this);
-
- arrayBufferPrototype.mark(this);
- dataViewPrototype.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayPrototype[i].mark(this);
-
- exceptionValue.mark(this);
-
- thrower->mark(this);
-
- if (m_qmlExtensions)
- m_qmlExtensions->markObjects(this);
-
classPool->markObjects(this);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
@@ -998,13 +923,6 @@ void ExecutionEngine::markObjects()
(*it)->markObjects(this);
}
-QmlExtensions *ExecutionEngine::qmlExtensions()
-{
- if (!m_qmlExtensions)
- m_qmlExtensions = new QmlExtensions;
- return m_qmlExtensions;
-}
-
ReturnedValue ExecutionEngine::throwError(const Value &value)
{
// we can get in here with an exception already set, as the runtime
@@ -1015,7 +933,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value)
return Encode::undefined();
hasException = true;
- exceptionValue = value;
+ *exceptionValue = value;
QV4::Scope scope(this);
QV4::Scoped<ErrorObject> error(scope, value);
if (!!error)
@@ -1036,8 +954,8 @@ ReturnedValue ExecutionEngine::catchException(StackTrace *trace)
*trace = exceptionStackTrace;
exceptionStackTrace.clear();
hasException = false;
- ReturnedValue res = exceptionValue.asReturnedValue();
- exceptionValue = Primitive::emptyValue();
+ ReturnedValue res = exceptionValue->asReturnedValue();
+ *exceptionValue = Primitive::emptyValue();
return res;
}
@@ -1170,7 +1088,7 @@ bool ExecutionEngine::recheckCStackLimits()
typedef QSet<QV4::Heap::Object *> V4ObjectSet;
static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value);
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects = 0);
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = 0);
static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value,
const QByteArray &targetType,
void **result);
@@ -1193,7 +1111,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
Q_ASSERT (!value.isEmpty());
QV4::Scope scope(e);
- if (QV4::VariantObject *v = value.as<QV4::VariantObject>())
+ if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
return v->d()->data;
if (typeHint == QVariant::Bool)
@@ -1205,10 +1123,10 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
if (typeHint == qMetaTypeId<QJSValue>())
return QVariant::fromValue(QJSValue(e, value.asReturnedValue()));
- if (value.asObject()) {
+ if (value.as<Object>()) {
QV4::ScopedObject object(scope, value);
if (typeHint == QMetaType::QJsonObject
- && !value.asArrayObject() && !value.asFunctionObject()) {
+ && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
return qVariantFromValue<QObject *>(wrapper->object());
@@ -1224,7 +1142,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return QV4::SequencePrototype::toVariant(object);
}
- if (value.asArrayObject()) {
+ if (value.as<ArrayObject>()) {
QV4::ScopedArrayObject a(scope, value);
if (typeHint == qMetaTypeId<QList<QObject *> >()) {
QList<QObject *> list;
@@ -1262,11 +1180,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return value.asDouble();
if (value.isString())
return value.stringValue()->toQString();
- if (QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
+ if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
return ld->d()->locale;
- if (QV4::DateObject *d = value.asDateObject())
+ if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
- if (QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
+ if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
return d->asByteArray();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
@@ -1282,7 +1200,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return objectToVariant(e, o, visitedObjects);
}
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects)
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects)
{
Q_ASSERT(o);
@@ -1293,7 +1211,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
- if (o->asArrayObject())
+ if (o->as<ArrayObject>())
return QVariantList();
return QVariantMap();
}
@@ -1301,7 +1219,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
QVariant result;
- if (o->asArrayObject()) {
+ if (o->as<ArrayObject>()) {
QV4::Scope scope(e);
QV4::ScopedArrayObject a(scope, o->asReturnedValue());
QV4::ScopedValue v(scope);
@@ -1314,7 +1232,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
}
result = list;
- } else if (!o->asFunctionObject()) {
+ } else if (!o->as<FunctionObject>()) {
QVariantMap map;
QV4::Scope scope(e);
QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
@@ -1492,7 +1410,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newVariantObject(variant));
}
-QVariantMap ExecutionEngine::variantMapFromJS(Object *o)
+QVariantMap ExecutionEngine::variantMapFromJS(const Object *o)
{
return objectToVariant(this, o).toMap();
}
@@ -1625,93 +1543,90 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
-void ExecutionEngine::assertObjectBelongsToEngine(const Value &v)
+void ExecutionEngine::assertObjectBelongsToEngine(const Heap::Base &baseObject)
{
- Q_UNUSED(v);
- Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this);
- Q_UNUSED(v);
+ Q_ASSERT(!baseObject.vtable->isObject || static_cast<const Heap::Object&>(baseObject).internalClass->engine == this);
+ Q_UNUSED(baseObject);
}
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
-bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *data)
+bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
{
- QV4::Scope scope(this);
-
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
case QMetaType::Bool:
- *reinterpret_cast<bool*>(data) = value.toBoolean();
+ *reinterpret_cast<bool*>(data) = value->toBoolean();
return true;
case QMetaType::Int:
- *reinterpret_cast<int*>(data) = value.toInt32();
+ *reinterpret_cast<int*>(data) = value->toInt32();
return true;
case QMetaType::UInt:
- *reinterpret_cast<uint*>(data) = value.toUInt32();
+ *reinterpret_cast<uint*>(data) = value->toUInt32();
return true;
case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
+ *reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
return true;
case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
+ *reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
return true;
case QMetaType::Double:
- *reinterpret_cast<double*>(data) = value.toNumber();
+ *reinterpret_cast<double*>(data) = value->toNumber();
return true;
case QMetaType::QString:
- if (value.isUndefined() || value.isNull())
+ if (value->isUndefined() || value->isNull())
*reinterpret_cast<QString*>(data) = QString();
else
- *reinterpret_cast<QString*>(data) = value.toQString();
+ *reinterpret_cast<QString*>(data) = value->toQString();
return true;
case QMetaType::Float:
- *reinterpret_cast<float*>(data) = value.toNumber();
+ *reinterpret_cast<float*>(data) = value->toNumber();
return true;
case QMetaType::Short:
- *reinterpret_cast<short*>(data) = short(value.toInt32());
+ *reinterpret_cast<short*>(data) = short(value->toInt32());
return true;
case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
+ *reinterpret_cast<unsigned short*>(data) = value->toUInt16();
return true;
case QMetaType::Char:
- *reinterpret_cast<char*>(data) = char(value.toInt32());
+ *reinterpret_cast<char*>(data) = char(value->toInt32());
return true;
case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
+ *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
return true;
case QMetaType::QChar:
- if (value.isString()) {
- QString str = value.stringValue()->toQString();
+ if (value->isString()) {
+ QString str = value->stringValue()->toQString();
*reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
} else {
- *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
+ *reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
}
return true;
case QMetaType::QDateTime:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
return true;
} break;
case QMetaType::QDate:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
return true;
} break;
case QMetaType::QRegExp:
- if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
+ if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
*reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
return true;
} break;
case QMetaType::QObjectStar: {
- QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>();
- if (qobjectWrapper || value.isNull()) {
- *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(scope.engine, value);
+ const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
+ if (qobjectWrapper || value->isNull()) {
+ *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(this, *value);
return true;
} break;
}
case QMetaType::QStringList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
*reinterpret_cast<QStringList *>(data) = a->toQStringList();
return true;
@@ -1719,15 +1634,15 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariantList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
- *reinterpret_cast<QVariantList *>(data) = scope.engine->toVariant(a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
+ *reinterpret_cast<QVariantList *>(data) = toVariant(*a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
return true;
}
break;
}
case QMetaType::QVariantMap: {
- QV4::ScopedObject o(scope, value);
+ const QV4::Object *o = value->as<QV4::Object>();
if (o) {
*reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
return true;
@@ -1735,20 +1650,19 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariant:
- *reinterpret_cast<QVariant*>(data) = scope.engine->toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ *reinterpret_cast<QVariant*>(data) = toVariant(*value, /*typeHint*/-1, /*createJSValueForObjects*/false);
return true;
case QMetaType::QJsonValue:
- *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
+ *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(*value);
return true;
case QMetaType::QJsonObject: {
- QV4::ScopedObject o(scope, value);
- *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(o);
+ *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value->as<Object>());
return true;
}
case QMetaType::QJsonArray: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<ArrayObject>();
if (a) {
- *reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(a);
+ *reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
return true;
}
break;
@@ -1758,7 +1672,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
{
- QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value);
+ const QQmlValueTypeWrapper *vtw = value->as<QQmlValueTypeWrapper>();
if (vtw && vtw->typeId() == type) {
return vtw->toGadget(data);
}
@@ -1783,21 +1697,22 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
#endif
- // Try to use magic; for compatibility with qscriptvalue_cast.
+ // Try to use magic; for compatibility with qjsvalue_cast.
QByteArray name = QMetaType::typeName(type);
- if (convertToNativeQObject(this, value, name, reinterpret_cast<void* *>(data)))
+ if (convertToNativeQObject(this, *value, name, reinterpret_cast<void* *>(data)))
return true;
- if (value.as<QV4::VariantObject>() && name.endsWith('*')) {
+ if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value.as<QV4::VariantObject>()->d()->data;
+ QVariant &var = value->as<QV4::VariantObject>()->d()->data;
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
return true;
- } else if (value.isObject()) {
+ } else if (value->isObject()) {
// Look in the prototype chain.
- QV4::ScopedObject proto(scope, value.objectValue()->prototype());
+ QV4::Scope scope(this);
+ QV4::ScopedObject proto(scope, value->objectValue()->prototype());
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
@@ -1807,7 +1722,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
else if (proto->as<QV4::QObjectWrapper>()) {
QByteArray className = name.left(name.size()-1);
QV4::ScopedObject p(scope, proto.getPointer());
- if (QObject *qobject = qtObjectFromJS(scope.engine, p))
+ if (QObject *qobject = qtObjectFromJS(this, p))
canCast = qobject->qt_metacast(className) != 0;
}
if (canCast) {
@@ -1821,11 +1736,11 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
proto = proto->prototype();
}
}
- } else if (value.isNull() && name.endsWith('*')) {
+ } else if (value->isNull() && name.endsWith('*')) {
*reinterpret_cast<void* *>(data) = 0;
return true;
} else if (type == qMetaTypeId<QJSValue>()) {
- *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value.asReturnedValue());
+ *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value->asReturnedValue());
return true;
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index c0c88abaa5..d4bcf363a2 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -37,6 +37,7 @@
#include "private/qv4isel_p.h"
#include "qv4managed_p.h"
#include "qv4context_p.h"
+#include "qv4internalclass_p.h"
#include <private/qintrusivelist_p.h>
namespace WTF {
@@ -50,6 +51,7 @@ class QV8Engine;
class QQmlError;
class QJSEngine;
class QQmlEngine;
+class QQmlContextData;
namespace QV4 {
namespace Debugging {
@@ -80,8 +82,6 @@ public:
Value *jsStackTop;
quint32 hasException;
- Heap::GlobalContext *m_rootContext;
- Heap::GlobalContext *rootContext() const { return m_rootContext; }
MemoryManager *memoryManager;
ExecutableAllocator *executableAllocator;
@@ -106,14 +106,19 @@ public:
--jsStackTop;
return jsStackTop->heapObject();
}
+ Value *jsAlloca(int nValues) {
+ Value *ptr = jsStackTop;
+ jsStackTop = ptr + nValues;
+ memset(ptr, 0, nValues*sizeof(Value));
+ return ptr;
+ }
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
QV4::Profiling::Profiler *profiler;
- Value m_globalObject;
- Object *globalObject() { return reinterpret_cast<Object *>(&m_globalObject); }
+ Object *globalObject;
Function *globalCode;
@@ -121,47 +126,97 @@ public:
QQmlEngine *qmlEngine() const;
QV8Engine *v8Engine;
- Value objectCtor;
- Value stringCtor;
- Value numberCtor;
- Value booleanCtor;
- Value arrayCtor;
- Value functionCtor;
- Value dateCtor;
- Value regExpCtor;
- Value errorCtor;
- Value evalErrorCtor;
- Value rangeErrorCtor;
- Value referenceErrorCtor;
- Value syntaxErrorCtor;
- Value typeErrorCtor;
- Value uRIErrorCtor;
- Value arrayBufferCtor;
- Value dataViewCtor;
- enum { NTypedArrayTypes = 9 }; // avoid header dependency
- Value typedArrayCtors[NTypedArrayTypes];
-
- Value objectPrototype;
- Value arrayPrototype;
- Value stringPrototype;
- Value numberPrototype;
- Value booleanPrototype;
- Value datePrototype;
- Value functionPrototype;
- Value regExpPrototype;
- Value errorPrototype;
- Value evalErrorPrototype;
- Value rangeErrorPrototype;
- Value referenceErrorPrototype;
- Value syntaxErrorPrototype;
- Value typeErrorPrototype;
- Value uRIErrorPrototype;
- Value variantPrototype;
- Value sequencePrototype;
-
- Value arrayBufferPrototype;
- Value dataViewPrototype;
- Value typedArrayPrototype[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here
+ enum JSObjects {
+ RootContect,
+ ObjectProto,
+ ArrayProto,
+ StringProto,
+ NumberProto,
+ BooleanProto,
+ DateProto,
+ FunctionProto,
+ RegExpProto,
+ ErrorProto,
+ EvalErrorProto,
+ RangeErrorProto,
+ ReferenceErrorProto,
+ SyntaxErrorProto,
+ TypeErrorProto,
+ URIErrorProto,
+ VariantProto,
+ SequenceProto,
+ ArrayBufferProto,
+ DataViewProto,
+ ValueTypeProto,
+
+ Object_Ctor,
+ String_Ctor,
+ Number_Ctor,
+ Boolean_Ctor,
+ Array_Ctor,
+ Function_Ctor,
+ Date_Ctor,
+ RegExp_Ctor,
+ Error_Ctor,
+ EvalError_Ctor,
+ RangeError_Ctor,
+ ReferenceError_Ctor,
+ SyntaxError_Ctor,
+ TypeError_Ctor,
+ URIError_Ctor,
+ ArrayBuffer_Ctor,
+ DataView_Ctor,
+
+ Eval_Function,
+ ThrowerObject,
+ NJSObjects
+ };
+ Value *jsObjects;
+ enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
+
+ GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContect); }
+ FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
+ FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
+ FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
+ FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
+ FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
+ FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
+ FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
+ FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
+ FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
+ FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
+ FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
+ FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
+ FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
+ FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
+ FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
+ FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
+ FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
+ FunctionObject *typedArrayCtors;
+
+ Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
+ Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
+ Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
+ Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
+ Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
+ Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
+ Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
+ Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
+ Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
+ Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
+ Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
+ Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
+ Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
+ Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
+ Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
+ Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
+ Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
+
+ Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
+ Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
+ Object *typedArrayPrototype;
+
+ Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
InternalClassPool *classPool;
InternalClass *emptyClass;
@@ -177,48 +232,89 @@ public:
InternalClass *argumentsObjectClass;
InternalClass *strictArgumentsObjectClass;
- Heap::EvalFunction *evalFunction;
- Heap::FunctionObject *thrower;
+ EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
+ FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
Property *argumentsAccessors;
int nArgumentsAccessors;
- StringValue id_empty;
- StringValue id_undefined;
- StringValue id_null;
- StringValue id_true;
- StringValue id_false;
- StringValue id_boolean;
- StringValue id_number;
- StringValue id_string;
- StringValue id_object;
- StringValue id_function;
- StringValue id_length;
- StringValue id_prototype;
- StringValue id_constructor;
- StringValue id_arguments;
- StringValue id_caller;
- StringValue id_callee;
- StringValue id_this;
- StringValue id___proto__;
- StringValue id_enumerable;
- StringValue id_configurable;
- StringValue id_writable;
- StringValue id_value;
- StringValue id_get;
- StringValue id_set;
- StringValue id_eval;
- StringValue id_uintMax;
- StringValue id_name;
- StringValue id_index;
- StringValue id_input;
- StringValue id_toString;
- StringValue id_destroy;
- StringValue id_valueOf;
- StringValue id_byteLength;
- StringValue id_byteOffset;
- StringValue id_buffer;
- StringValue id_lastIndex;
+ enum JSStrings {
+ String_Empty,
+ String_undefined,
+ String_null,
+ String_true,
+ String_false,
+ String_boolean,
+ String_number,
+ String_string,
+ String_object,
+ String_function,
+ String_length,
+ String_prototype,
+ String_constructor,
+ String_arguments,
+ String_caller,
+ String_callee,
+ String_this,
+ String___proto__,
+ String_enumerable,
+ String_configurable,
+ String_writable,
+ String_value,
+ String_get,
+ String_set,
+ String_eval,
+ String_uintMax,
+ String_name,
+ String_index,
+ String_input,
+ String_toString,
+ String_destroy,
+ String_valueOf,
+ String_byteLength,
+ String_byteOffset,
+ String_buffer,
+ String_lastIndex,
+ NJSStrings
+ };
+ Value *jsStrings;
+
+ String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
+ String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
+ String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
+ String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
+ String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
+ String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
+ String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
+ String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
+ String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
+ String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
+ String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
+ String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
+ String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
+ String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
+ String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
+ String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
+ String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
+ String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
+ String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
+ String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
+ String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
+ String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
+ String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
+ String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
+ String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
+ String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
+ String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
+ String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
+ String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
+ String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
+ String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
+ String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
+ String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
+ String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
+ String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
+ String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
QSet<CompiledData::CompilationUnit*> compilationUnits;
@@ -261,7 +357,7 @@ public:
Heap::String *newString(const QString &s = QString());
Heap::String *newIdentifier(const QString &text);
- Heap::Object *newStringObject(const Value &value);
+ Heap::Object *newStringObject(const String *string);
Heap::Object *newNumberObject(double value);
Heap::Object *newBooleanObject(bool b);
@@ -291,7 +387,10 @@ public:
Heap::Object *newForEachIteratorObject(Object *o);
- Heap::Object *qmlContextObject() const;
+ QV4::Heap::QmlContextWrapper *qmlContextObject() const;
+ QObject *qmlScopeObject() const;
+ QQmlContextData *callingQmlContext() const;
+
StackTrace stackTrace(int frameLimit = -1) const;
StackFrame currentStackFrame() const;
@@ -305,12 +404,10 @@ public:
InternalClass *newClass(const InternalClass &other);
- QmlExtensions *qmlExtensions();
-
bool recheckCStackLimits();
// Exception handling
- Value exceptionValue;
+ Value *exceptionValue;
StackTrace exceptionStackTrace;
ReturnedValue throwError(const Value &value);
@@ -335,15 +432,12 @@ public:
QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
QV4::ReturnedValue fromVariant(const QVariant &);
- QVariantMap variantMapFromJS(QV4::Object *o);
+ QVariantMap variantMapFromJS(const QV4::Object *o);
- bool metaTypeFromJS(const Value &value, int type, void *data);
+ bool metaTypeFromJS(const Value *value, int type, void *data);
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
- void assertObjectBelongsToEngine(const Value &v);
-
-private:
- QmlExtensions *m_qmlExtensions;
+ void assertObjectBelongsToEngine(const Heap::Base &baseObject);
};
inline void ExecutionEngine::pushContext(CallContext *context)
@@ -376,29 +470,26 @@ Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
}
-// ### Remove me
inline
-void Managed::mark(QV4::ExecutionEngine *engine)
+void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
Q_ASSERT(inUse());
- if (markBit())
+ if (isMarked())
return;
#ifndef QT_NO_DEBUG
engine->assertObjectBelongsToEngine(*this);
#endif
- d()->setMarkBit();
- engine->pushForGC(d());
+ setMarkBit();
+ engine->pushForGC(this);
}
-
-inline
-void Heap::Base::mark(QV4::ExecutionEngine *engine)
+inline void Value::mark(ExecutionEngine *e)
{
- Q_ASSERT(inUse());
- if (isMarked())
+ if (!val)
return;
- setMarkBit();
- engine->pushForGC(this);
+ Managed *m = as<Managed>();
+ if (m)
+ m->d()->mark(e);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 9034dee6a0..3c0a05483c 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -33,11 +33,14 @@
#include "qv4errorobject_p.h"
-#include "qv4mm_p.h"
+#include <QtCore/qnumeric.h>
+#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
+#include "qv4string_p.h"
+#include <private/qv4mm_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
@@ -179,57 +182,57 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const Value &msg)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, SyntaxError)
+ : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, SyntaxError)
{
}
Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, SyntaxError)
+ : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, fileName, lineNumber, columnNumber, SyntaxError)
{
}
Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype.asObject(), message, EvalError)
+ : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype(), message, EvalError)
{
}
Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
{
}
Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
{
}
Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
+ : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
{
}
Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
+ : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
{
}
Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, ReferenceError)
+ : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), msg, fileName, lineNumber, columnNumber, ReferenceError)
{
}
Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
{
}
Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
{
}
Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype.asObject(), message, URIError)
+ : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype(), message, URIError)
{
}
@@ -251,16 +254,16 @@ Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name)
{
}
-ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const ErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return Encode(scope.engine->newErrorObject(v));
}
-ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
+ReturnedValue ErrorCtor::call(const Managed *that, CallData *callData)
{
- return static_cast<Object *>(that)->construct(callData);
+ return static_cast<const Object *>(that)->construct(callData);
}
Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
@@ -268,9 +271,9 @@ Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue EvalErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<EvalErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const EvalErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<EvalErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -280,9 +283,9 @@ Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RangeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<RangeErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const RangeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -292,9 +295,9 @@ Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ReferenceErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ReferenceErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const ReferenceErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -304,9 +307,9 @@ Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue SyntaxErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<SyntaxErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const SyntaxErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -316,9 +319,9 @@ Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<TypeErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const TypeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -328,9 +331,9 @@ Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue URIErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<URIErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const URIErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -340,10 +343,10 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj)
Scope scope(engine);
ScopedString s(scope);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = obj));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
obj->defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- obj->defineDefaultProperty(engine->id_toString, method_toString, 0);
+ obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
obj->defineDefaultProperty(QStringLiteral("message"), (s = engine->newString()));
}
@@ -351,11 +354,11 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
- ScopedValue name(scope, o->get(ctx->d()->engine->id_name));
+ ScopedValue name(scope, o->get(ctx->d()->engine->id_name()));
QString qname;
if (name->isUndefined())
qname = QString::fromLatin1("Error");
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 071f5b8c9a..da2c978e5f 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -62,7 +62,7 @@ struct ErrorObject : Object {
ErrorType errorType;
StackTrace stackTrace;
- String *stack;
+ Pointer<String> stack;
};
struct EvalErrorObject : ErrorObject {
@@ -141,8 +141,8 @@ struct ErrorObject: Object {
};
template<>
-inline ErrorObject *value_cast(const Value &v) {
- return v.asErrorObject();
+inline const ErrorObject *Value::as() const {
+ return isManaged() && m && m->vtable->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : 0;
}
struct EvalErrorObject: ErrorObject {
@@ -183,50 +183,50 @@ struct ErrorCtor: FunctionObject
{
V4_OBJECT2(ErrorCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct EvalErrorCtor: ErrorCtor
{
V4_OBJECT2(EvalErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct RangeErrorCtor: ErrorCtor
{
V4_OBJECT2(RangeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct ReferenceErrorCtor: ErrorCtor
{
V4_OBJECT2(ReferenceErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct SyntaxErrorCtor: ErrorCtor
{
V4_OBJECT2(SyntaxErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct TypeErrorCtor: ErrorCtor
{
V4_OBJECT2(TypeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct URIErrorCtor: ErrorCtor
{
V4_OBJECT2(URIErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index efe6c7c226..a18a2d4919 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -34,10 +34,10 @@
#include "qv4function_p.h"
#include "qv4managed_p.h"
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4engine_p.h"
#include "qv4lookup_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 0a12d013ac..d8cdda477a 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4function_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4arrayobject_p.h"
#include "qv4scopedvalue_p.h"
@@ -63,7 +63,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -73,7 +73,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -84,7 +84,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -95,7 +95,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject())
+ : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
, scope(scope)
, function(Q_NULLPTR)
{
@@ -106,7 +106,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -117,7 +117,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject())
+ : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
, scope(scope)
, function(Q_NULLPTR)
{
@@ -129,7 +129,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu
Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
: Heap::Object(ic, prototype)
- , scope(ic->engine->rootContext())
+ , scope(ic->engine->rootContext()->d())
, function(Q_NULLPTR)
{
Scope scope(ic->engine);
@@ -152,7 +152,7 @@ void FunctionObject::init(String *n, bool createProto)
ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype);
if (createProto) {
- ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype.asObject()));
+ ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype()));
proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor);
proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue();
memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue();
@@ -161,12 +161,12 @@ void FunctionObject::init(String *n, bool createProto)
}
ScopedValue v(s, n);
- defineReadonlyProperty(s.engine->id_name, v);
+ defineReadonlyProperty(s.engine->id_name(), v);
}
-ReturnedValue FunctionObject::name()
+ReturnedValue FunctionObject::name() const
{
- return get(scope()->engine->id_name);
+ return get(scope()->engine->id_name());
}
@@ -177,13 +177,12 @@ ReturnedValue FunctionObject::newInstance()
return construct(callData);
}
-ReturnedValue FunctionObject::construct(Managed *that, CallData *)
+ReturnedValue FunctionObject::construct(const Managed *that, CallData *)
{
- static_cast<FunctionObject *>(that)->internalClass()->engine->throwTypeError();
- return Encode::undefined();
+ return static_cast<const FunctionObject *>(that)->engine()->throwTypeError();
}
-ReturnedValue FunctionObject::call(Managed *, CallData *)
+ReturnedValue FunctionObject::call(const Managed *, CallData *)
{
return Encode::undefined();
}
@@ -237,10 +236,10 @@ Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
}
// 15.3.2
-ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
{
- Scope scope(static_cast<Object *>(that)->engine());
- Scoped<FunctionCtor> f(scope, static_cast<FunctionCtor *>(that));
+ Scope scope(static_cast<const Object *>(that)->engine());
+ Scoped<FunctionCtor> f(scope, static_cast<const FunctionCtor *>(that));
ScopedContext ctx(scope, scope.engine->currentContext());
QString arguments;
QString body;
@@ -287,7 +286,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
}
// 15.3.1: This is equivalent to new Function(...)
-ReturnedValue FunctionCtor::call(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -304,12 +303,12 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- defineReadonlyProperty(engine->id_length, Primitive::fromInt32(0));
+ defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
defineDefaultProperty(QStringLiteral("call"), method_call, 1);
defineDefaultProperty(QStringLiteral("bind"), method_bind, 1);
@@ -318,7 +317,7 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
{
- FunctionObject *fun = ctx->thisObject().asFunctionObject();
+ FunctionObject *fun = ctx->thisObject().as<FunctionObject>();
if (!fun)
return ctx->engine()->throwTypeError();
@@ -328,7 +327,7 @@ ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -370,7 +369,7 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -409,15 +408,15 @@ Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *fun
{
}
-ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
@@ -441,15 +440,15 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
return obj.asReturnedValue();
}
-ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
ScopedContext context(scope, v4->currentContext());
Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
@@ -458,7 +457,7 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction);
+ QmlContextWrapper::registerQmlDependencies(scope.engine, f->function()->compiledFunction);
return result->asReturnedValue();
}
@@ -466,7 +465,7 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype.asObject())
+ : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype())
{
this->scope = scope->d();
@@ -481,7 +480,7 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
if (createProto) {
ScopedString name(s, function->name());
f->init(name, createProto);
- f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
+ f->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(f->formalParameterCount()));
} else {
f->ensureMemberIndex(s.engine, Index_Length);
memberData->data[Index_Name] = function->name();
@@ -490,22 +489,22 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
if (scope->d()->strictMode) {
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(scope->d()->engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(scope->d()->engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
}
-ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
@@ -536,15 +535,15 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
return result.asReturnedValue();
}
-ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<SimpleScriptFunction *>(that)->internalClass()->engine;
+ ExecutionEngine *v4 = static_cast<const SimpleScriptFunction *>(that)->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
@@ -575,7 +574,7 @@ Heap::Object *SimpleScriptFunction::protoForConstructor()
ScopedObject p(scope, protoProperty());
if (p)
return p->d();
- return scope.engine->objectPrototype.asObject()->d();
+ return scope.engine->objectPrototype()->d();
}
@@ -588,14 +587,14 @@ Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String
{
}
-ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
+ReturnedValue BuiltinFunction::construct(const Managed *f, CallData *)
{
- return static_cast<BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
+ return static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
}
-ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
{
- BuiltinFunction *f = static_cast<BuiltinFunction *>(that);
+ const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
@@ -614,9 +613,9 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
return f->d()->code(sctx);
}
-ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData)
{
- IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
+ const IndexedBuiltinFunction *f = static_cast<const IndexedBuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
@@ -650,24 +649,24 @@ Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionOb
Scope s(scope);
ScopedObject f(s, this);
- ScopedValue l(s, target->get(s.engine->id_length));
+ ScopedValue l(s, target->get(s.engine->id_length()));
int len = l->toUInt32();
if (boundArgs)
len -= boundArgs->size();
if (len < 0)
len = 0;
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(len));
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
-ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::call(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
@@ -685,9 +684,9 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
return t->call(callData);
}
-ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 252ff40a1a..930b65156f 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -36,7 +36,7 @@
#include "qv4object_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +65,7 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
bool needsActivation() const { return function ? function->needsActivation() : false; }
- ExecutionContext *scope;
+ Pointer<ExecutionContext> scope;
Function *function;
};
@@ -102,9 +102,9 @@ struct ScriptFunction : SimpleScriptFunction {
struct BoundFunction : FunctionObject {
BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
- FunctionObject *target;
+ Pointer<FunctionObject> target;
Value boundThis;
- MemberData *boundArgs;
+ Pointer<MemberData> boundArgs;
};
}
@@ -117,12 +117,12 @@ struct Q_QML_EXPORT FunctionObject: Object {
Q_MANAGED_TYPE(FunctionObject)
V4_NEEDS_DESTROY
- Heap::ExecutionContext *scope() { return d()->scope; }
- Function *function() { return d()->function; }
+ Heap::ExecutionContext *scope() const { return d()->scope; }
+ Function *function() const { return d()->function; }
- ReturnedValue name();
- unsigned int formalParameterCount() { return d()->formalParameterCount(); }
- unsigned int varCount() { return d()->varCount(); }
+ ReturnedValue name() const;
+ unsigned int formalParameterCount() const { return d()->formalParameterCount(); }
+ unsigned int varCount() const { return d()->varCount(); }
void init(String *name, bool createProto);
@@ -130,12 +130,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
using Object::construct;
using Object::call;
- static ReturnedValue construct(Managed *that, CallData *);
- static ReturnedValue call(Managed *that, CallData *d);
-
- static FunctionObject *cast(const Value &v) {
- return v.asFunctionObject();
- }
+ static ReturnedValue construct(const Managed *that, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *d);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
@@ -152,16 +148,17 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
template<>
-inline FunctionObject *value_cast(const Value &v) {
- return v.asFunctionObject();
+inline const FunctionObject *Value::as() const {
+ return isManaged() && m && m->vtable->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : 0;
}
+
struct FunctionCtor: FunctionObject
{
V4_OBJECT2(FunctionCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct FunctionPrototype: FunctionObject
@@ -184,20 +181,20 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code);
}
- static ReturnedValue construct(Managed *, CallData *);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct IndexedBuiltinFunction: FunctionObject
{
V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *)
+ static ReturnedValue construct(const Managed *m, CallData *)
{
- return static_cast<IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
+ return static_cast<const IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
}
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index,
@@ -212,8 +209,8 @@ Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scop
struct SimpleScriptFunction: FunctionObject {
V4_OBJECT2(SimpleScriptFunction, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
Heap::Object *protoForConstructor();
};
@@ -221,8 +218,8 @@ struct SimpleScriptFunction: FunctionObject {
struct ScriptFunction: SimpleScriptFunction {
V4_OBJECT2(ScriptFunction, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
@@ -234,12 +231,12 @@ struct BoundFunction: FunctionObject {
return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
}
- Heap::FunctionObject *target() { return d()->target; }
+ Heap::FunctionObject *target() const { return d()->target; }
Value boundThis() const { return d()->boundThis; }
Heap::MemberData *boundArgs() const { return d()->boundArgs; }
- static ReturnedValue construct(Managed *, CallData *d);
- static ReturnedValue call(Managed *that, CallData *dd);
+ static ReturnedValue construct(const Managed *, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *dd);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 4b08194b60..6d7135cbaa 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -88,6 +88,8 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#define V4_ENABLE_JIT
#endif
+#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
+#define V4_ENABLE_JIT
#endif
// Black list some platforms
@@ -168,7 +170,7 @@ struct Property;
struct Value;
struct Lookup;
struct ArrayData;
-struct ManagedVTable;
+struct VTable;
struct BooleanObject;
struct NumberObject;
@@ -211,7 +213,6 @@ class WeakValue;
struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
-struct QmlExtensions;
namespace Global {
enum {
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 8e33cec57f..3b1f09e502 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -32,13 +32,14 @@
****************************************************************************/
#include "qv4globalobject_p.h"
-#include "qv4mm_p.h"
-#include "qv4value_inl_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
#include "qv4context_p.h"
#include "qv4function_p.h"
#include "qv4debugging_p.h"
#include "qv4script_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -339,14 +340,14 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
DEFINE_OBJECT_VTABLE(EvalFunction);
Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval())
{
Scope s(scope);
ScopedFunctionObject f(s, this);
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1));
}
-ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
+ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
{
if (callData->argc < 1)
return Encode::undefined();
@@ -399,10 +400,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
}
-ReturnedValue EvalFunction::call(Managed *that, CallData *callData)
+ReturnedValue EvalFunction::call(const Managed *that, CallData *callData)
{
// indirect call
- return static_cast<EvalFunction *>(that)->evalCall(callData, false);
+ return static_cast<const EvalFunction *>(that)->evalCall(callData, false);
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 74de233b47..ba1d5d2e0b 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -52,10 +52,10 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
{
V4_OBJECT2(EvalFunction, FunctionObject)
- ReturnedValue evalCall(CallData *callData, bool directCall);
+ ReturnedValue evalCall(CallData *callData, bool directCall) const;
using Object::construct;
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct GlobalFunctions
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index e4bd460966..2eb61081c7 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -54,7 +54,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContex
: v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
{
m_qmlglobal.set(engine, qmlglobal);
- if (callback.asFunctionObject())
+ if (callback.as<QV4::FunctionObject>())
m_callbackFunction.set(engine, callback);
m_resultObject.set(v4, resultValue(v4));
@@ -94,14 +94,14 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
{
if (!callback.isObject())
return;
- QV4::ExecutionEngine *v4 = callback.asObject()->engine();
+ QV4::ExecutionEngine *v4 = callback.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, callback);
if (!f)
return;
QV4::ScopedCallData callData(scope, 1);
- callData->thisObject = v4->globalObject()->asReturnedValue();
+ callData->thisObject = v4->globalObject->asReturnedValue();
callData->args[0] = status;
f->call(callData);
if (scope.hasException())
@@ -176,7 +176,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
return QV4::Encode::undefined();
QV4::Scope scope(ctx->engine());
- QQmlContextData *context = QV4::QmlContextWrapper::callingContext(scope.engine);
+ QQmlContextData *context = scope.engine->callingQmlContext();
if (!context || !context->isJSContext)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
@@ -184,7 +184,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
- if (ctx->argc() >= 2 && ctx->args()[1].asFunctionObject())
+ if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
callbackFunction = ctx->args()[1];
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
@@ -224,7 +224,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QV4::ScopedValue ex(scope, scope.engine->catchException());
result = resultValue(scope.engine, Exception);
QV4::ScopedString exception(scope, scope.engine->newString(QStringLiteral("exception")));
- result->asObject()->put(exception, ex);
+ result->as<QV4::Object>()->put(exception, ex);
} else {
result = resultValue(scope.engine, Ok);
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 5dc94e8555..5ef4442b03 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -50,7 +50,7 @@
#include <private/qqmlcontext_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4context_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 3289058cb7..80590fe72e 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -46,7 +46,7 @@ struct String;
struct ExecutionEngine;
struct Object;
struct Identifier;
-struct ManagedVTable;
+struct VTable;
struct PropertyHashData;
struct PropertyHash
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index e7905974df..d634e783bd 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -38,8 +38,8 @@
#include <qv4objectiterator_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4runtime_p.h>
+#include "qv4string_p.h"
-#include <qjsondocument.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -62,33 +62,6 @@ static int indent = 0;
DEFINE_OBJECT_VTABLE(JsonObject);
-class JsonParser
-{
-public:
- JsonParser(ExecutionEngine *engine, const QChar *json, int length);
-
- ReturnedValue parse(QJsonParseError *error);
-
-private:
- inline bool eatSpace();
- inline QChar nextToken();
-
- ReturnedValue parseObject();
- ReturnedValue parseArray();
- bool parseMember(Object *o);
- bool parseString(QString *string);
- bool parseValue(Value *val);
- bool parseNumber(Value *val);
-
- ExecutionEngine *engine;
- const QChar *head;
- const QChar *json;
- const QChar *end;
-
- int nestingLevel;
- QJsonParseError::ParseError lastError;
-};
-
static const int nestingLimit = 1024;
@@ -639,17 +612,22 @@ bool JsonParser::parseString(QString *string)
struct Stringify
{
- ExecutionContext *ctx;
+ ExecutionEngine *v4;
FunctionObject *replacerFunction;
- // ### GC
- QVector<Heap::String *> propertyList;
+ QV4::String *propertyList;
+ int propertyListSize;
QString gap;
QString indent;
+ QStack<Object *> stack;
- // ### GC
- QStack<Heap::Object *> stack;
+ bool stackContains(Object *o) {
+ for (int i = 0; i < stack.size(); ++i)
+ if (stack.at(i)->d() == o->d())
+ return true;
+ return false;
+ }
- Stringify(ExecutionContext *ctx) : ctx(ctx), replacerFunction(0) {}
+ Stringify(ExecutionEngine *e) : v4(e), replacerFunction(0), propertyList(0), propertyListSize(0) {}
QString Str(const QString &key, const Value &v);
QString JA(ArrayObject *a);
@@ -701,26 +679,26 @@ static QString quote(const QString &str)
QString Stringify::Str(const QString &key, const Value &v)
{
- Scope scope(ctx);
+ Scope scope(v4);
ScopedValue value(scope, v);
ScopedObject o(scope, value);
if (o) {
- ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
+ ScopedString s(scope, v4->newString(QStringLiteral("toJSON")));
ScopedFunctionObject toJSON(scope, o->get(s));
if (!!toJSON) {
ScopedCallData callData(scope, 1);
callData->thisObject = value;
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
value = toJSON->call(callData);
}
}
if (replacerFunction) {
- ScopedObject holder(scope, ctx->d()->engine->newObject());
+ ScopedObject holder(scope, v4->newObject());
holder->put(scope.engine, QString(), value);
ScopedCallData callData(scope, 2);
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
callData->args[1] = value;
callData->thisObject = holder;
value = replacerFunction->call(callData);
@@ -728,11 +706,11 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (NumberObject *n = o->asNumberObject())
+ if (NumberObject *n = o->as<NumberObject>())
value = Encode(n->value());
- else if (StringObject *so = o->asStringObject())
- value = so->d()->value;
- else if (BooleanObject *b =o->asBooleanObject())
+ else if (StringObject *so = o->as<StringObject>())
+ value = so->d()->string;
+ else if (BooleanObject *b = o->as<BooleanObject>())
value = Encode(b->value());
}
@@ -750,8 +728,8 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (!o->asFunctionObject()) {
- if (o->asArrayObject()) {
+ if (!o->as<FunctionObject>()) {
+ if (o->as<ArrayObject>()) {
return JA(static_cast<ArrayObject *>(o.getPointer()));
} else {
return JO(o);
@@ -777,20 +755,20 @@ QString Stringify::makeMember(const QString &key, const Value &v)
QString Stringify::JO(Object *o)
{
- if (stack.contains(o->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(o)) {
+ v4->throwTypeError();
return QString();
}
- Scope scope(ctx);
+ Scope scope(v4);
QString result;
- stack.push(o->d());
+ stack.push(o);
QString stepback = indent;
indent += gap;
QStringList partial;
- if (propertyList.isEmpty()) {
+ if (!propertyListSize) {
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -805,11 +783,13 @@ QString Stringify::JO(Object *o)
partial += member;
}
} else {
- ScopedString s(scope);
- for (int i = 0; i < propertyList.size(); ++i) {
+ ScopedValue v(scope);
+ for (int i = 0; i < propertyListSize; ++i) {
bool exists;
- s = propertyList.at(i);
- ScopedValue v(scope, o->get(s, &exists));
+ String *s = propertyList + i;
+ if (!s)
+ continue;
+ v = o->get(s, &exists);
if (!exists)
continue;
QString member = makeMember(s->toQString(), v);
@@ -834,15 +814,15 @@ QString Stringify::JO(Object *o)
QString Stringify::JA(ArrayObject *a)
{
- if (stack.contains(a->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(a)) {
+ v4->throwTypeError();
return QString();
}
Scope scope(a->engine());
QString result;
- stack.push(a->d());
+ stack.push(a);
QString stepback = indent;
indent += gap;
@@ -879,7 +859,7 @@ QString Stringify::JA(ArrayObject *a)
Heap::JsonObject::JsonObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype.asObject())
+ : Heap::Object(e->emptyClass, e->objectPrototype())
{
Scope scope(e);
ScopedObject o(scope, this);
@@ -911,32 +891,38 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
{
Scope scope(ctx);
- Stringify stringify(ctx);
+ Stringify stringify(scope.engine);
ScopedObject o(scope, ctx->argument(1));
if (o) {
- stringify.replacerFunction = o->asFunctionObject();
+ stringify.replacerFunction = o->as<FunctionObject>();
if (o->isArrayObject()) {
uint arrayLen = o->getLength();
- ScopedValue v(scope);
+ stringify.propertyList = static_cast<QV4::String *>(scope.alloc(arrayLen));
for (uint i = 0; i < arrayLen; ++i) {
- v = o->getIndexed(i);
- if (v->asNumberObject() || v->asStringObject() || v->isNumber())
- v = RuntimeHelpers::toString(scope.engine, v);
- if (v->isString()) {
- String *s = v->stringValue();
- if (!stringify.propertyList.contains(s->d()))
- stringify.propertyList.append(s->d());
+ Value *v = stringify.propertyList + i;
+ *v = o->getIndexed(i);
+ if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber())
+ *v = RuntimeHelpers::toString(scope.engine, *v);
+ if (!v->isString()) {
+ v->m = 0;
+ } else {
+ for (uint j = 0; j <i; ++j) {
+ if (stringify.propertyList[j].m == v->m) {
+ v->m = 0;
+ break;
+ }
+ }
}
}
}
}
ScopedValue s(scope, ctx->argument(2));
- if (NumberObject *n = s->asNumberObject())
+ if (NumberObject *n = s->as<NumberObject>())
s = Encode(n->value());
- else if (StringObject *so = s->asStringObject())
- s = so->d()->value;
+ else if (StringObject *so = s->as<StringObject>())
+ s = so->d()->string;
if (s->isNumber()) {
stringify.gap = QString(qMin(10, (int)s->toInteger()), ' ');
@@ -986,7 +972,7 @@ QJsonValue JsonObject::toJsonValue(const Value &value, V4ObjectSet &visitedObjec
return QJsonValue(value.toQString());
Q_ASSERT(value.isObject());
- Scope scope(value.asObject()->engine());
+ Scope scope(value.as<Object>()->engine());
ScopedArrayObject a(scope, value);
if (a)
return toJsonArray(a, visitedObjects);
@@ -1009,22 +995,22 @@ QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJs
return o.asReturnedValue();
}
-QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
+QJsonObject JsonObject::toJsonObject(const Object *o, V4ObjectSet &visitedObjects)
{
QJsonObject result;
- if (!o || o->asFunctionObject())
+ if (!o || o->as<FunctionObject>())
return result;
Scope scope(o->engine());
- if (visitedObjects.contains(o->d())) {
+ if (visitedObjects.contains(ObjectItem(o))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
return result;
}
- visitedObjects.insert(o->d());
+ visitedObjects.insert(ObjectItem(o));
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -1035,11 +1021,11 @@ QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
break;
QString key = name->toQStringNoThrow();
- if (!val->asFunctionObject())
+ if (!val->as<FunctionObject>())
result.insert(key, toJsonValue(val, visitedObjects));
}
- visitedObjects.remove(o->d());
+ visitedObjects.remove(ObjectItem(o));
return result;
}
@@ -1057,7 +1043,7 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
return a.asReturnedValue();
}
-QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
+QJsonArray JsonObject::toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects)
{
QJsonArray result;
if (!a)
@@ -1065,25 +1051,25 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
Scope scope(a->engine());
- if (visitedObjects.contains(a->d())) {
+ if (visitedObjects.contains(ObjectItem(a))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty array (and no error is thrown).
return result;
}
- visitedObjects.insert(a->d());
+ visitedObjects.insert(ObjectItem(a));
ScopedValue v(scope);
quint32 length = a->getLength();
for (quint32 i = 0; i < length; ++i) {
v = a->getIndexed(i);
- if (v->asFunctionObject())
+ if (v->as<FunctionObject>())
v = Encode::null();
result.append(toJsonValue(v, visitedObjects));
}
- visitedObjects.remove(a->d());
+ visitedObjects.remove(ObjectItem(a));
return result;
}
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 81a783ee92..1ad0e2c5de 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -37,6 +37,8 @@
#include <qjsonarray.h>
#include <qjsonobject.h>
#include <qjsonvalue.h>
+#include <qjsondocument.h>
+#include <qhash.h>
QT_BEGIN_NAMESPACE
@@ -50,12 +52,23 @@ struct JsonObject : Object {
}
+struct ObjectItem {
+ const QV4::Object *o;
+ ObjectItem(const QV4::Object *o) : o(o) {}
+};
+
+inline bool operator ==(const ObjectItem &a, const ObjectItem &b)
+{ return a.o->d() == b.o->d(); }
+
+inline int qHash(const ObjectItem &i, uint seed = 0)
+{ return ::qHash((void *)i.o->d(), seed); }
+
struct JsonObject : Object {
Q_MANAGED_TYPE(JsonObject)
V4_OBJECT2(JsonObject, Object)
private:
- // ### GC
- typedef QSet<QV4::Heap::Base *> V4ObjectSet;
+
+ typedef QSet<ObjectItem> V4ObjectSet;
public:
static ReturnedValue method_parse(CallContext *ctx);
@@ -67,18 +80,45 @@ public:
static inline QJsonValue toJsonValue(const QV4::Value &value)
{ V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); }
- static inline QJsonObject toJsonObject(QV4::Object *o)
+ static inline QJsonObject toJsonObject(const QV4::Object *o)
{ V4ObjectSet visitedObjects; return toJsonObject(o, visitedObjects); }
- static inline QJsonArray toJsonArray(QV4::ArrayObject *a)
+ static inline QJsonArray toJsonArray(const QV4::ArrayObject *a)
{ V4ObjectSet visitedObjects; return toJsonArray(a, visitedObjects); }
private:
static QJsonValue toJsonValue(const QV4::Value &value, V4ObjectSet &visitedObjects);
- static QJsonObject toJsonObject(Object *o, V4ObjectSet &visitedObjects);
- static QJsonArray toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects);
+ static QJsonObject toJsonObject(const Object *o, V4ObjectSet &visitedObjects);
+ static QJsonArray toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects);
};
+class JsonParser
+{
+public:
+ JsonParser(ExecutionEngine *engine, const QChar *json, int length);
+
+ ReturnedValue parse(QJsonParseError *error);
+
+private:
+ inline bool eatSpace();
+ inline QChar nextToken();
+
+ ReturnedValue parseObject();
+ ReturnedValue parseArray();
+ bool parseMember(Object *o);
+ bool parseString(QString *string);
+ bool parseValue(Value *val);
+ bool parseNumber(Value *val);
+
+ ExecutionEngine *engine;
+ const QChar *head;
+ const QChar *json;
+ const QChar *end;
+
+ int nestingLevel;
+ QJsonParseError::ParseError lastError;
+};
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 82b20337cb..443427b024 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -33,6 +33,7 @@
#include "qv4lookup_p.h"
#include "qv4functionobject_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -72,7 +73,7 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
return Primitive::emptyValue().asReturnedValue();
}
-ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs)
+ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs)
{
Heap::Object *obj = thisObject->d();
ExecutionEngine *engine = thisObject->engine();
@@ -123,7 +124,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -168,7 +169,7 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
@@ -200,7 +201,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
uint idx = index.asArrayIndex();
if (idx < UINT_MAX) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = value;
return;
@@ -224,7 +225,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = v;
return;
@@ -235,7 +236,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (Object *o = object.asObject())
+ if (const Object *o = object.as<Object>())
return o->getLookup(l);
Object *proto;
@@ -244,14 +245,14 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
case Value::Null_Type:
return engine->throwTypeError();
case Value::Boolean_Type:
- proto = engine->booleanPrototype.asObject();
+ proto = engine->booleanPrototype();
break;
case Value::Managed_Type: {
Q_ASSERT(object.isString());
- proto = engine->stringPrototype.asObject();
+ proto = engine->stringPrototype();
Scope scope(engine);
ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(engine->id_length)) {
+ if (name->equals(engine->id_length())) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
return stringLengthGetter(l, engine, object);
@@ -260,7 +261,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
}
case Value::Integer_Type:
default: // Number
- proto = engine->numberPrototype.asObject();
+ proto = engine->numberPrototype();
}
PropertyAttributes attrs;
@@ -291,7 +292,7 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const
Lookup l1 = *l;
if (l1.getter == Lookup::getter0 || l1.getter == Lookup::getter1) {
- if (Object *o = object.asObject()) {
+ if (const Object *o = object.as<Object>()) {
ReturnedValue v = o->getLookup(l);
Lookup l2 = *l;
@@ -560,7 +561,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (String *s = object.asString())
+ if (const String *s = object.as<String>())
return Encode(s->d()->length());
l->getter = getterGeneric;
@@ -569,7 +570,7 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, con
ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (ArrayObject *a = object.asArrayObject())
+ if (const ArrayObject *a = object.as<ArrayObject>())
return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
l->getter = getterGeneric;
@@ -579,7 +580,7 @@ ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, cons
ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -608,7 +609,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass())
return o->memberData()->data[l->index].asReturnedValue();
@@ -618,7 +619,7 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
return o->prototype()->memberData->data[l->index].asReturnedValue();
@@ -629,7 +630,7 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
if (l->classList[1] == o->internalClass) {
@@ -645,7 +646,7 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
@@ -662,7 +663,7 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
@@ -680,7 +681,7 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
if (l->classList[1] == o->internalClass) {
@@ -701,7 +702,7 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
return globalGetterGeneric(l, engine);
}
-void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Scope scope(engine);
ScopedObject o(scope, object);
@@ -716,11 +717,11 @@ void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &obje
o->setLookup(l, value);
}
-void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Lookup l1 = *l;
- if (Object *o = object.asObject()) {
+ if (Object *o = object.as<Object>()) {
o->setLookup(l, value);
if (l->setter == Lookup::setter0) {
@@ -735,7 +736,7 @@ void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &o
setterFallback(l, engine, object, value);
}
-void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
QV4::Scope scope(engine);
QV4::ScopedObject o(scope, object.toObject(scope.engine));
@@ -745,9 +746,9 @@ void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &obj
}
}
-void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
o->memberData()->data[l->index] = value;
return;
@@ -756,9 +757,9 @@ void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, co
setterTwoClasses(l, engine, object, value);
}
-void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
if (!o->memberData() || l->index >= o->memberData()->size)
@@ -773,9 +774,9 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
@@ -791,9 +792,9 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
@@ -812,9 +813,9 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o) {
if (o->internalClass() == l->classList[0]) {
o->memberData()->data[l->index] = value;
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 88397dc36c..232e909c48 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -51,7 +51,7 @@ struct Lookup {
void (*indexedSetter)(Lookup *l, const Value &object, const Value &index, const Value &v);
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
- void (*setter)(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &v);
+ void (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
};
union {
ExecutionEngine *engine;
@@ -107,17 +107,17 @@ struct Lookup {
static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionEngine *engine);
static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionEngine *engine);
- static void setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
+ static void setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
ReturnedValue lookup(const Value &thisObject, Object *obj, PropertyAttributes *attrs);
- ReturnedValue lookup(Object *obj, PropertyAttributes *attrs);
+ ReturnedValue lookup(const Object *obj, PropertyAttributes *attrs);
};
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index c4b9fc597e..546190086e 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -32,13 +32,13 @@
****************************************************************************/
#include "qv4managed_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4errorobject_p.h"
using namespace QV4;
-const ManagedVTable Managed::static_vtbl =
+const VTable Managed::static_vtbl =
{
0,
Managed::IsExecutionContext,
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 0fe5c7ee49..7cce80d087 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -35,7 +35,7 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
+#include <private/qv4heap_p.h>
QT_BEGIN_NAMESPACE
@@ -65,8 +65,8 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
- static const QV4::ManagedVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
+ static const QV4::VTable static_vtbl; \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
V4_MANAGED_SIZE_TEST \
QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
@@ -86,23 +86,6 @@ struct GCDeletable
bool lastCall;
};
-struct ManagedVTable
-{
- const ManagedVTable * const parent;
- uint isExecutionContext : 1;
- uint isString : 1;
- uint isObject : 1;
- uint isFunctionObject : 1;
- uint isErrorObject : 1;
- uint isArrayData : 1;
- uint unused : 18;
- uint type : 8;
- const char *className;
- void (*destroy)(Heap::Base *);
- void (*markObjects)(Heap::Base *, ExecutionEngine *e);
- bool (*isEqualTo)(Managed *m, Managed *other);
-};
-
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
parentVTable, \
@@ -121,7 +104,7 @@ struct ManagedVTable
}
#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
+const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
struct Q_QML_PRIVATE_EXPORT Managed : Value
{
@@ -141,8 +124,6 @@ private:
public:
- inline void mark(QV4::ExecutionEngine *engine);
-
enum Type {
Type_Invalid,
Type_String,
@@ -167,46 +148,6 @@ public:
};
Q_MANAGED_TYPE(Invalid)
- template <typename T>
- T *as() {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
- template <typename T>
- const T *as() const {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this)));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
-
- String *asString() { return d()->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
- Object *asObject() { return d()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
- ArrayObject *asArrayObject() { return d()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
- FunctionObject *asFunctionObject() { return d()->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
- BooleanObject *asBooleanObject() { return d()->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
- NumberObject *asNumberObject() { return d()->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
- StringObject *asStringObject() { return d()->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
- DateObject *asDateObject() { return d()->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
- ErrorObject *asErrorObject() { return d()->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
- ArgumentsObject *asArgumentsObject() { return d()->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
-
bool isListType() const { return d()->vtable->type == Type_QmlSequence; }
bool isArrayObject() const { return d()->vtable->type == Type_ArrayObject; }
@@ -231,37 +172,15 @@ private:
template<>
-inline Managed *value_cast(const Value &v) {
- return v.asManaged();
-}
-
-template<typename T>
-inline T *managed_cast(Managed *m)
-{
- return m ? m->as<T>() : 0;
+inline const Managed *Value::as() const {
+ if (isManaged())
+ return managed();
+ return 0;
}
template<>
-inline String *managed_cast(Managed *m)
-{
- return m ? m->asString() : 0;
-}
-template<>
-inline Object *managed_cast(Managed *m)
-{
- return m ? m->asObject() : 0;
-}
-template<>
-inline FunctionObject *managed_cast(Managed *m)
-{
- return m ? m->asFunctionObject() : 0;
-}
-
-inline Value Value::fromManaged(Managed *m)
-{
- if (!m)
- return QV4::Primitive::undefinedValue();
- return *m;
+inline const Object *Value::as() const {
+ return isManaged() && m && m->vtable->isObject ? objectValue() : 0;
}
}
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 473e05bf88..c498160c36 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -48,7 +48,7 @@ DEFINE_OBJECT_VTABLE(MathObject);
static const double qt_PI = 2.0 * ::asin(1.0);
Heap::MathObject::MathObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype.asObject())
+ : Heap::Object(e->emptyClass, e->objectPrototype())
{
Scope scope(e);
ScopedObject m(scope, this);
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index 03dfee3dcf..5ec5cb1f58 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -32,7 +32,8 @@
****************************************************************************/
#include "qv4memberdata_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
using namespace QV4;
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 89ff110b20..36b83090e1 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -33,6 +33,7 @@
#include "qv4numberobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
@@ -50,14 +51,14 @@ Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
+ReturnedValue NumberCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(m->cast<NumberCtor>()->engine());
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(scope.engine->newNumberObject(dbl));
}
-ReturnedValue NumberCtor::call(Managed *, CallData *callData)
+ReturnedValue NumberCtor::call(const Managed *, CallData *callData)
{
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(dbl);
@@ -67,8 +68,8 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(qSNaN()));
ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));
@@ -85,9 +86,9 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
#endif
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
+ defineDefaultProperty(engine->id_toString(), method_toString);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
defineDefaultProperty(QStringLiteral("toFixed"), method_toFixed, 1);
defineDefaultProperty(QStringLiteral("toExponential"), method_toExponential);
defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision);
@@ -97,7 +98,7 @@ inline ReturnedValue thisNumberValue(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asReturnedValue();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return Encode(n->value());
@@ -107,7 +108,7 @@ inline double thisNumber(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asDouble();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return n->value();
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 205995701b..04798d31fc 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -53,8 +53,8 @@ struct NumberCtor: FunctionObject
{
V4_OBJECT2(NumberCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
};
struct NumberPrototype: NumberObject
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 211fd1812e..b4ad477e89 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -37,12 +37,13 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4lookup_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4memberdata_p.h"
#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
+#include "qv4string_p.h"
#include <stdint.h>
@@ -138,7 +139,7 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ScopedString s(scope, e->newIdentifier(name));
ScopedContext global(scope, e->rootContext());
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
- function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@@ -148,7 +149,7 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
Scope scope(e);
ScopedContext global(scope, e->rootContext());
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
- function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@@ -219,50 +220,50 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
}
// Section 8.12.1
-Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs)
+void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
- return __getOwnProperty__(idx, attrs);
+ return getOwnProperty(idx, attrs, p);
uint member = internalClass()->find(name);
if (member < UINT_MAX) {
- if (attrs)
- *attrs = internalClass()->propertyData[member];
- return propertyAt(member);
+ *attrs = internalClass()->propertyData[member];
+ if (p)
+ p->copy(propertyAt(member), *attrs);
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
-Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
+void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
{
- Property *p = arrayData() ? arrayData()->getProperty(index) : 0;
- if (p) {
- if (attrs)
- *attrs = arrayData()->attributes(index);
- return p;
+ Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
+ if (pd) {
+ *attrs = arrayData()->attributes(index);
+ if (p)
+ p->copy(pd, *attrs);
+ return;
}
if (isStringObject()) {
- if (attrs)
- *attrs = Attr_NotConfigurable|Attr_NotWritable;
- return static_cast<StringObject *>(this)->getIndex(index);
+ *attrs = Attr_NotConfigurable|Attr_NotWritable;
+ if (p)
+ p->value = static_cast<StringObject *>(this)->getIndex(index);
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
// Section 8.12.2
Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const
{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return __getPropertyDescriptor__(idx, attrs);
-
+ Q_ASSERT(name->asArrayIndex() == UINT_MAX);
const Heap::Object *o = d();
while (o) {
@@ -286,16 +287,15 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
while (o) {
Property *p = o->arrayData ? o->arrayData->getProperty(index) : 0;
if (p) {
- if (attrs)
- *attrs = o->arrayData->attributes(index);
+ *attrs = o->arrayData->attributes(index);
return p;
}
if (o->vtable->type == Type_StringObject) {
- Property *p = static_cast<const Heap::StringObject *>(o)->getIndex(index);
- if (p) {
- if (attrs)
- *attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return p;
+ if (index < static_cast<const Heap::StringObject *>(o)->length()) {
+ // this is an evil hack, but it works, as the method is only ever called from putIndexed,
+ // where we don't use the returned pointer there for non writable attributes
+ *attrs = (Attr_NotWritable|Attr_NotConfigurable);
+ return reinterpret_cast<Property *>(0x1);
}
}
o = o->prototype;
@@ -356,8 +356,7 @@ bool Object::hasOwnProperty(uint index) const
return true;
if (isStringObject()) {
- String *s = static_cast<const StringObject *>(this)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(this)->length())
return true;
}
if (!queryIndexed(index).isEmpty())
@@ -365,24 +364,24 @@ bool Object::hasOwnProperty(uint index) const
return false;
}
-ReturnedValue Object::construct(Managed *m, CallData *)
+ReturnedValue Object::construct(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::call(Managed *m, CallData *)
+ReturnedValue Object::call(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGet(name, hasProperty);
+ return static_cast<const Object *>(m)->internalGet(name, hasProperty);
}
-ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty);
+ return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty);
}
void Object::put(Managed *m, String *name, const Value &value)
@@ -416,8 +415,7 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
return o->arrayData()->attributes(index);
if (o->isStringObject()) {
- String *s = static_cast<const StringObject *>(o)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(o)->length())
return (Attr_NotWritable|Attr_NotConfigurable);
}
return Attr_Invalid;
@@ -433,9 +431,9 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
}
-ReturnedValue Object::getLookup(Managed *m, Lookup *l)
+ReturnedValue Object::getLookup(const Managed *m, Lookup *l)
{
- Object *o = static_cast<Object *>(m);
+ const Object *o = static_cast<const Object *>(m);
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -531,7 +529,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
while (it->arrayNode != o->sparseEnd()) {
int k = it->arrayNode->key();
uint pidx = it->arrayNode->value;
- Heap::SparseArrayData *sa = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>();
Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx);
it->arrayNode = it->arrayNode->nextNode();
PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data;
@@ -548,7 +546,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// dense arrays
while (it->arrayIndex < o->d()->arrayData->len) {
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Value &val = sa->data(it->arrayIndex);
PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex);
++it->arrayIndex;
@@ -585,7 +583,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// Section 8.12.3
-ReturnedValue Object::internalGet(String *name, bool *hasProperty)
+ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -611,7 +609,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
+ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
{
Property *pd = 0;
PropertyAttributes attrs;
@@ -625,10 +623,12 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
break;
}
if (o->isStringObject()) {
- pd = static_cast<StringObject *>(o.getPointer())->getIndex(index);
- if (pd) {
+ ScopedString str(scope, static_cast<StringObject *>(o.getPointer())->getIndex(index));
+ if (str) {
attrs = (Attr_NotWritable|Attr_NotConfigurable);
- break;
+ if (hasProperty)
+ *hasProperty = true;
+ return str.asReturnedValue();
}
}
o = o->prototype();
@@ -674,7 +674,7 @@ void Object::internalPut(String *name, const Value &value)
goto reject;
} else if (!attrs.isWritable())
goto reject;
- else if (isArrayObject() && name->equals(engine()->id_length)) {
+ else if (isArrayObject() && name->equals(engine()->id_length())) {
bool ok;
uint l = value.asArrayLength(&ok);
if (!ok) {
@@ -710,7 +710,7 @@ void Object::internalPut(String *name, const Value &value)
// Clause 5
if (pd && attrs.isAccessor()) {
- assert(pd->setter() != 0);
+ Q_ASSERT(pd->setter() != 0);
Scope scope(engine());
ScopedFunctionObject setter(scope, pd->setter());
@@ -745,8 +745,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
attrs = arrayData()->attributes(index);
if (!pd && isStringObject()) {
- pd = static_cast<StringObject *>(this)->getIndex(index);
- if (pd)
+ if (index < static_cast<StringObject *>(this)->length())
// not writable
goto reject;
}
@@ -784,7 +783,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
// Clause 5
if (pd && attrs.isAccessor()) {
- assert(pd->setter() != 0);
+ Q_ASSERT(pd->setter() != 0);
Scope scope(engine());
ScopedFunctionObject setter(scope, pd->setter());
@@ -858,8 +857,8 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
PropertyAttributes *cattrs;
uint memberIndex;
- if (isArrayObject() && name->equals(engine->id_length)) {
- Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length));
+ if (isArrayObject() && name->equals(engine->id_length())) {
+ Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()));
Property *lp = propertyAt(Heap::ArrayObject::LengthPropertyIndex);
cattrs = internalClass()->propertyData.constData() + Heap::ArrayObject::LengthPropertyIndex;
if (attrs.isEmpty() || p->isSubset(attrs, lp, *cattrs))
@@ -926,16 +925,16 @@ reject:
bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
{
- Property *current = 0;
+ bool hasProperty = 0;
// Clause 1
if (arrayData()) {
- current = arrayData()->getProperty(index);
- if (!current && isStringObject())
- current = static_cast<StringObject *>(this)->getIndex(index);
+ hasProperty = arrayData()->getProperty(index);
+ if (!hasProperty && isStringObject())
+ hasProperty = (index < static_cast<StringObject *>(this)->length());
}
- if (!current) {
+ if (!hasProperty) {
// clause 3
if (!isExtensible())
goto reject;
@@ -1097,7 +1096,7 @@ void Object::copyArrayData(Object *other)
uint Object::getLength(const Managed *m)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length));
+ ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length()));
return v->toUInt32();
}
@@ -1137,7 +1136,7 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
+ : Heap::Object(engine->arrayClass, engine->arrayPrototype())
{
init();
Scope scope(engine);
@@ -1155,14 +1154,14 @@ Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
a->setArrayLengthUnchecked(len);
}
-ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
+ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(scope.engine->id_length)) {
+ if (name->equals(scope.engine->id_length())) {
// special case, as the property is on the object itself
l->getter = Lookup::arrayLengthGetter;
- ArrayObject *a = static_cast<ArrayObject *>(m);
+ const ArrayObject *a = static_cast<const ArrayObject *>(m);
return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
}
return Object::getLookup(m, l);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 71a997e133..671e207489 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -36,6 +36,9 @@
#include "qv4managed_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraydata_p.h"
+#include "qv4engine_p.h"
+#include "qv4scopedvalue_p.h"
+#include "qv4value_p.h"
QT_BEGIN_NAMESPACE
@@ -44,20 +47,16 @@ namespace QV4 {
namespace Heap {
struct Object : Base {
- Object(ExecutionEngine *engine)
- : internalClass(engine->emptyClass),
- prototype(static_cast<Object *>(engine->objectPrototype.m))
- {
- }
+ inline Object(ExecutionEngine *engine);
Object(InternalClass *internal, QV4::Object *prototype);
const Property *propertyAt(uint index) const { return reinterpret_cast<const Property *>(memberData->data + index); }
Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData->data + index); }
InternalClass *internalClass;
- Heap::Object *prototype;
- MemberData *memberData;
- ArrayData *arrayData;
+ Pointer<Object> prototype;
+ Pointer<MemberData> memberData;
+ Pointer<ArrayData> arrayData;
};
}
@@ -67,7 +66,7 @@ struct Object : Base {
Q_MANAGED_CHECK \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
Data *d() const { return static_cast<Data *>(m); }
@@ -77,24 +76,24 @@ struct Object : Base {
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
struct ObjectVTable
{
- ManagedVTable managedVTable;
- ReturnedValue (*call)(Managed *, CallData *data);
- ReturnedValue (*construct)(Managed *, CallData *data);
- ReturnedValue (*get)(Managed *, String *name, bool *hasProperty);
- ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
+ VTable vTable;
+ ReturnedValue (*call)(const Managed *, CallData *data);
+ ReturnedValue (*construct)(const Managed *, CallData *data);
+ ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty);
+ ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
void (*put)(Managed *, String *name, const Value &value);
void (*putIndexed)(Managed *, uint index, const Value &value);
PropertyAttributes (*query)(const Managed *, String *name);
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
- ReturnedValue (*getLookup)(Managed *m, Lookup *l);
+ ReturnedValue (*getLookup)(const Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const Value &v);
uint (*getLength)(const Managed *m);
void (*advanceIterator)(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
@@ -103,7 +102,7 @@ struct ObjectVTable
#define DEFINE_OBJECT_VTABLE(classname) \
const QV4::ObjectVTable classname::static_vtbl = \
{ \
- DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \
+ DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.vTable), \
call, \
construct, \
get, \
@@ -145,11 +144,11 @@ struct Q_QML_EXPORT Object: Managed {
Heap::Object *prototype() const { return d()->prototype; }
bool setPrototype(Object *proto);
- Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0);
- Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0);
+ void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
+ void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
- Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs = 0) const;
- Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const;
+ Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const;
+ Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const;
bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
@@ -272,9 +271,9 @@ public:
}
void ensureMemberIndex(uint idx);
- inline ReturnedValue get(String *name, bool *hasProperty = 0)
+ inline ReturnedValue get(String *name, bool *hasProperty = 0) const
{ return vtable()->get(this, name, hasProperty); }
- inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
+ inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) const
{ return vtable()->getIndexed(this, idx, hasProperty); }
inline void put(String *name, const Value &v)
{ vtable()->put(this, name, v); }
@@ -288,7 +287,7 @@ public:
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
{ return vtable()->deleteIndexedProperty(this, index); }
- ReturnedValue getLookup(Lookup *l)
+ ReturnedValue getLookup(Lookup *l) const
{ return vtable()->getLookup(this, l); }
void setLookup(Lookup *l, const Value &v)
{ vtable()->setLookup(this, l, v); }
@@ -296,30 +295,30 @@ public:
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
- inline ReturnedValue construct(CallData *d)
+ inline ReturnedValue construct(CallData *d) const
{ return vtable()->construct(this, d); }
- inline ReturnedValue call(CallData *d)
+ inline ReturnedValue call(CallData *d) const
{ return vtable()->call(this, d); }
protected:
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue construct(Managed *m, CallData *);
- static ReturnedValue call(Managed *m, CallData *);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue construct(const Managed *m, CallData *);
+ static ReturnedValue call(const Managed *m, CallData *);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const Value &v);
static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
private:
- ReturnedValue internalGet(String *name, bool *hasProperty);
- ReturnedValue internalGetIndexed(uint index, bool *hasProperty);
+ ReturnedValue internalGet(String *name, bool *hasProperty) const;
+ ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
void internalPut(String *name, const Value &value);
void internalPutIndexed(uint index, const Value &value);
bool internalDeleteProperty(String *name);
@@ -331,6 +330,12 @@ private:
namespace Heap {
+inline Object::Object(ExecutionEngine *engine)
+ : internalClass(engine->emptyClass),
+ prototype(static_cast<Object *>(engine->objectPrototype()->m))
+{
+}
+
struct BooleanObject : Object {
BooleanObject(InternalClass *ic, QV4::Object *prototype)
: Object(ic, prototype),
@@ -339,7 +344,7 @@ struct BooleanObject : Object {
}
BooleanObject(ExecutionEngine *engine, bool b)
- : Object(engine->emptyClass, engine->booleanPrototype.asObject()),
+ : Object(engine->emptyClass, engine->booleanPrototype()),
b(b)
{
}
@@ -354,7 +359,7 @@ struct NumberObject : Object {
}
NumberObject(ExecutionEngine *engine, double val)
- : Object(engine->emptyClass, engine->numberPrototype.asObject()),
+ : Object(engine->emptyClass, engine->numberPrototype()),
value(val)
{
}
@@ -367,7 +372,7 @@ struct ArrayObject : Object {
};
ArrayObject(ExecutionEngine *engine)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
+ : Heap::Object(engine->arrayClass, engine->arrayPrototype())
{ init(); }
ArrayObject(ExecutionEngine *engine, const QStringList &list);
ArrayObject(InternalClass *ic, QV4::Object *prototype)
@@ -400,7 +405,7 @@ struct ArrayObject: Object {
void init(ExecutionEngine *engine);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
using Object::getLength;
static uint getLength(const Managed *m);
@@ -454,14 +459,10 @@ inline void Object::arraySet(uint index, const Value &value)
setArrayLengthUnchecked(index + 1);
}
-template<>
-inline Object *value_cast(const Value &v) {
- return v.asObject();
-}
template<>
-inline ArrayObject *value_cast(const Value &v) {
- return v.asArrayObject();
+inline const ArrayObject *Value::as() const {
+ return isManaged() && m && m->vtable->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : 0;
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index f36ee554a7..d0e2650feb 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -35,6 +35,7 @@
#include "qv4stringobject_p.h"
#include "qv4identifier_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -50,7 +51,7 @@ ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scrat
init(o);
}
-ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
+ObjectIterator::ObjectIterator(Scope &scope, const Object *o, uint flags)
: engine(scope.engine)
, object(scope.alloc(1))
, current(scope.alloc(1))
@@ -62,7 +63,7 @@ ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
init(o);
}
-void ObjectIterator::init(Object *o)
+void ObjectIterator::init(const Object *o)
{
object->m = o ? o->m : 0;
current->m = o ? o->m : 0;
@@ -83,7 +84,7 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
*name = 0;
*index = UINT_MAX;
- if (!object->asObject()) {
+ if (!object->as<Object>()) {
*attrs = PropertyAttributes();
return;
}
@@ -92,19 +93,19 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ScopedString n(scope);
while (1) {
- if (!current->asObject())
+ if (!current->as<Object>())
break;
while (1) {
- current->asObject()->advanceIterator(this, name, index, pd, attrs);
+ current->as<Object>()->advanceIterator(this, name, index, pd, attrs);
if (attrs->isEmpty())
break;
// check the property is not already defined earlier in the proto chain
if (current->heapObject() != object->heapObject()) {
- o = object->asObject();
+ o = object->as<Object>();
n = *name;
bool shadowed = false;
- while (o->asObject()->d() != current->heapObject()) {
+ while (o->d() != current->heapObject()) {
if ((!!n && o->hasOwnProperty(n)) ||
(*index != UINT_MAX && o->hasOwnProperty(*index))) {
shadowed = true;
@@ -131,7 +132,7 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ReturnedValue ObjectIterator::nextPropertyName(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -147,13 +148,13 @@ ReturnedValue ObjectIterator::nextPropertyName(Value *value)
if (!!name)
return name->asReturnedValue();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(index);
}
ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -169,13 +170,13 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
if (!!name)
return name->asReturnedValue();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(engine->newString(QString::number(index)));
}
ReturnedValue ObjectIterator::nextPropertyNameAsString()
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index a7abd2ca10..ff568ba893 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -57,8 +57,8 @@ struct Q_QML_EXPORT ObjectIterator
uint flags;
ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags);
- ObjectIterator(Scope &scope, Object *o, uint flags);
- void init(Object *o);
+ ObjectIterator(Scope &scope, const Object *o, uint flags);
+ void init(const Object *o);
void next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(Value *value);
ReturnedValue nextPropertyNameAsString(Value *value);
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 9356ea434e..41483e9ef5 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -34,10 +34,11 @@
#include "qv4objectproto_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
@@ -52,14 +53,14 @@ Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
+ReturnedValue ObjectCtor::construct(const Managed *that, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(that);
ExecutionEngine *v4 = ctor->engine();
Scope scope(v4);
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
ScopedObject obj(scope, v4->newObject());
- ScopedObject proto(scope, ctor->get(v4->id_prototype));
+ ScopedObject proto(scope, ctor->get(v4->id_prototype()));
if (!!proto)
obj->setPrototype(proto);
return obj.asReturnedValue();
@@ -67,9 +68,9 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
return RuntimeHelpers::toObject(scope.engine, callData->args[0]);
}
-ReturnedValue ObjectCtor::call(Managed *m, CallData *callData)
+ReturnedValue ObjectCtor::call(const Managed *m, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(m);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(m);
ExecutionEngine *v4 = ctor->engine();
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull())
return v4->newObject()->asReturnedValue();
@@ -81,8 +82,8 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
Scope scope(v4);
ScopedObject o(scope, this);
- ctor->defineReadonlyProperty(v4->id_prototype, o);
- ctor->defineReadonlyProperty(v4->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(v4->id_prototype(), o);
+ ctor->defineReadonlyProperty(v4->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyNames"), method_getOwnPropertyNames, 1);
@@ -98,9 +99,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("keys"), method_keys, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(v4->id_toString, method_toString, 0);
+ defineDefaultProperty(v4->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
- defineDefaultProperty(v4->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(v4->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("hasOwnProperty"), method_hasOwnProperty, 1);
defineDefaultProperty(QStringLiteral("isPrototypeOf"), method_isPrototypeOf, 1);
defineDefaultProperty(QStringLiteral("propertyIsEnumerable"), method_propertyIsEnumerable, 1);
@@ -109,9 +110,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ScopedContext global(scope, scope.engine->rootContext());
ScopedProperty p(scope);
- p->value = BuiltinFunction::create(global, v4->id___proto__, method_get_proto);
- p->set = BuiltinFunction::create(global, v4->id___proto__, method_set_proto);
- insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
+ p->value = BuiltinFunction::create(global, v4->id___proto__(), method_get_proto);
+ p->set = BuiltinFunction::create(global, v4->id___proto__(), method_set_proto);
+ insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
@@ -140,8 +141,9 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property *desc = O->__getOwnProperty__(name, &attrs);
- return fromPropertyDescriptor(scope.engine, desc, attrs);
+ Property desc;
+ O->getOwnProperty(name, &attrs, &desc);
+ return fromPropertyDescriptor(scope.engine, &desc, attrs);
}
ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
@@ -163,7 +165,7 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
return ctx->engine()->throwTypeError();
ScopedObject newObject(scope, ctx->d()->engine->newObject());
- newObject->setPrototype(O->asObject());
+ newObject->setPrototype(O->as<Object>());
if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) {
ctx->d()->callData->args[0] = newObject.asReturnedValue();
@@ -400,7 +402,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
ScopedObject o(scope, ctx->thisObject().toObject(scope.engine));
if (!o)
return Encode::undefined();
- ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString));
+ ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString()));
if (!f)
return ctx->engine()->throwTypeError();
ScopedCallData callData(scope);
@@ -462,7 +464,7 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
PropertyAttributes attrs;
- o->__getOwnProperty__(p, &attrs);
+ o->getOwnProperty(p, &attrs);
return Encode(attrs.isEnumerable());
}
@@ -484,7 +486,7 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -512,7 +514,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -525,7 +527,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject().asObject());
+ ScopedObject o(scope, ctx->thisObject().as<Object>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -572,15 +574,15 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(engine->id_enumerable))
- attrs->setEnumerable((tmp = o->get(engine->id_enumerable))->toBoolean());
+ if (o->hasProperty(engine->id_enumerable()))
+ attrs->setEnumerable((tmp = o->get(engine->id_enumerable()))->toBoolean());
- if (o->hasProperty(engine->id_configurable))
- attrs->setConfigurable((tmp = o->get(engine->id_configurable))->toBoolean());
+ if (o->hasProperty(engine->id_configurable()))
+ attrs->setConfigurable((tmp = o->get(engine->id_configurable()))->toBoolean());
- if (o->hasProperty(engine->id_get)) {
- ScopedValue get(scope, o->get(engine->id_get));
- FunctionObject *f = get->asFunctionObject();
+ if (o->hasProperty(engine->id_get())) {
+ ScopedValue get(scope, o->get(engine->id_get()));
+ FunctionObject *f = get->as<FunctionObject>();
if (f || get->isUndefined()) {
desc->value = get;
} else {
@@ -590,9 +592,9 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_set)) {
- ScopedValue set(scope, o->get(engine->id_set));
- FunctionObject *f = set->asFunctionObject();
+ if (o->hasProperty(engine->id_set())) {
+ ScopedValue set(scope, o->get(engine->id_set()));
+ FunctionObject *f = set->as<FunctionObject>();
if (f || set->isUndefined()) {
desc->set = set;
} else {
@@ -602,22 +604,22 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_writable)) {
+ if (o->hasProperty(engine->id_writable())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- attrs->setWritable((tmp = o->get(engine->id_writable))->toBoolean());
+ attrs->setWritable((tmp = o->get(engine->id_writable()))->toBoolean());
// writable forces it to be a data descriptor
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(engine->id_value)) {
+ if (o->hasProperty(engine->id_value())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- desc->value = o->get(engine->id_value);
+ desc->value = o->get(engine->id_value());
attrs->setType(PropertyAttributes::Data);
}
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 4e96681017..d571e50cd4 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -53,8 +53,8 @@ struct ObjectCtor: FunctionObject
{
V4_OBJECT2(ObjectCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ObjectPrototype: Object
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 88dc1946b8..a21bf696aa 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4persistent_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4object_p.h"
#include "PageAllocation.h"
@@ -190,7 +190,7 @@ void PersistentValueStorage::mark(ExecutionEngine *e)
Page *p = static_cast<Page *>(firstPage);
while (p) {
for (int i = 0; i < kEntriesPerPage; ++i) {
- if (Managed *m = p->values[i].asManaged())
+ if (Managed *m = p->values[i].as<Managed>())
m->mark(e);
}
drainMarkStack(e, markBase);
@@ -312,6 +312,12 @@ WeakValue::WeakValue(const WeakValue &other)
}
}
+WeakValue::WeakValue(ExecutionEngine *engine, const Value &value)
+{
+ val = engine->memoryManager->m_weakValues->allocate();
+ *val = value;
+}
+
WeakValue &WeakValue::operator=(const WeakValue &other)
{
if (!val) {
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 7cac2ed95f..858734e9ed 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -33,7 +33,8 @@
#ifndef QV4PERSISTENT_H
#define QV4PERSISTENT_H
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
+#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
@@ -96,7 +97,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template<typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
@@ -122,6 +129,7 @@ class Q_QML_EXPORT WeakValue
public:
WeakValue() : val(0) {}
WeakValue(const WeakValue &other);
+ WeakValue(ExecutionEngine *engine, const Value &value);
WeakValue &operator=(const WeakValue &other);
~WeakValue();
@@ -138,7 +146,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template <typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index a7019d0558..d2628c7bd0 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -32,7 +32,8 @@
****************************************************************************/
#include "qv4profiling_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include <private/qv4string_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 1b55abd1f7..34d9cdadeb 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -35,7 +35,6 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
QT_BEGIN_NAMESPACE
@@ -73,8 +72,8 @@ struct Property {
inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(value.heapObject()) : 0; }
inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; }
- inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
- inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(s)) : Value::fromHeapObject(0); }
+ inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
+ inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : 0); }
void copy(const Property *other, PropertyAttributes attrs) {
value = other->value;
@@ -85,8 +84,8 @@ struct Property {
explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
explicit Property(Value v) : value(v) { set = Value::fromHeapObject(0); }
Property(FunctionObject *getter, FunctionObject *setter) {
- value = Primitive::fromManaged(reinterpret_cast<Managed *>(getter));
- set = Primitive::fromManaged(reinterpret_cast<Managed *>(setter));
+ value = reinterpret_cast<Managed *>(getter);
+ set = reinterpret_cast<Managed *>(setter);
}
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
value.m = reinterpret_cast<Heap::Base *>(getter);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 1e4718c208..4f6331c54b 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -55,6 +55,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4mm_p.h>
#include <private/qqmlscriptstring_p.h>
@@ -97,7 +98,7 @@ static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function)
static QPair<QObject *, int> extractQtSignal(const Value &value)
{
if (value.isObject()) {
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject function(scope, value);
if (function)
@@ -240,8 +241,8 @@ Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
{
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
}
QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
@@ -260,7 +261,7 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
}
ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
- bool *hasProperty, bool includeImports)
+ bool *hasProperty, bool includeImports) const
{
if (QQmlData::wasDeleted(d()->object)) {
if (hasProperty)
@@ -271,8 +272,8 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
QV4::Scope scope(engine());
QV4::ScopedString name(scope, n);
- if (name->equals(scope.engine->id_destroy) || name->equals(scope.engine->id_toString)) {
- int index = name->equals(scope.engine->id_destroy) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
+ if (name->equals(scope.engine->id_destroy()) || name->equals(scope.engine->id_toString())) {
+ int index = name->equals(scope.engine->id_destroy()) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
ScopedContext global(scope, scope.engine->rootContext());
QV4::ScopedValue method(scope, QV4::QObjectMethod::create(global, d()->object, index));
if (hasProperty)
@@ -322,13 +323,12 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
- ScopedContext ctx(scope, scope.engine->currentContext());
- return getProperty(d()->object, ctx, result);
+ return getProperty(scope.engine, d()->object, result);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine);
QQmlData::flushPendingBinding(object, property->coreIndex);
@@ -338,16 +338,16 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- QV4::ScopedObject qmlcontextobject(scope, ctx->d()->engine->qmlContextObject());
+ QV4::ScopedObject qmlcontextobject(scope, engine->qmlContextObject());
ScopedContext global(scope, scope.engine->rootContext());
return QV4::QObjectMethod::create(global, object, property->coreIndex, qmlcontextobject);
} else if (property->isSignalHandler()) {
- QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(ctx->d()->engine, object, property->coreIndex));
+ QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(engine, object, property->coreIndex));
- QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect")));
- QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(connect)));
- handler->put(disconnect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(disconnect)));
+ QV4::ScopedString connect(scope, engine->newIdentifier(QStringLiteral("connect")));
+ QV4::ScopedString disconnect(scope, engine->newIdentifier(QStringLiteral("disconnect")));
+ handler->put(connect, QV4::ScopedValue(scope, engine->functionPrototype()->get(connect)));
+ handler->put(disconnect, QV4::ScopedValue(scope, engine->functionPrototype()->get(disconnect)));
return handler.asReturnedValue();
} else {
@@ -365,31 +365,32 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine, object, *property, nptr));
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
if (captureRequired) {
if (property->accessors->notifier) {
- if (n)
- ep->captureProperty(n);
+ if (n && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(n);
} else {
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
}
}
return rv->asReturnedValue();
}
- if (captureRequired && ep && !property->isConstant())
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex);
} else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Direct>(engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Indirect>(engine, object, *property, 0);
}
}
@@ -440,21 +441,21 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
Scope scope(engine);
ScopedContext ctx(scope, engine->currentContext());
- setProperty(object, ctx, result, value);
+ setProperty(engine, object, result, value);
return true;
}
-void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value)
{
if (!property->isWritable() && !property->isQList()) {
QString error = QLatin1String("Cannot assign to read-only property \"") +
property->name(object) + QLatin1Char('\"');
- ctx->engine()->throwTypeError(error);
+ engine->throwTypeError(error);
return;
}
QQmlBinding *newBinding = 0;
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine);
QV4::ScopedFunctionObject f(scope, value);
if (f) {
if (!f->isBinding()) {
@@ -465,25 +466,25 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
} else {
// binding assignment.
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
newBinding = new QQmlBinding(value, object, callingQmlContext);
- newBinding->setTarget(object, *property, callingQmlContext);
+ newBinding->setTarget(object, *property);
}
}
- QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
- if (oldBinding)
- oldBinding->destroy();
+ if (newBinding)
+ QQmlPropertyPrivate::setBinding(newBinding);
+ else
+ QQmlPropertyPrivate::removeBinding(object, property->encodedIndex());
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
@@ -510,16 +511,16 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else if (value.isUndefined() && property->propType == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
} else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
- PROPERTY_STORE(QJSValue, QJSValue(ctx->d()->engine, value.asReturnedValue()));
+ PROPERTY_STORE(QJSValue, QJSValue(scope.engine, value.asReturnedValue()));
} else if (value.isUndefined() && property->propType != qMetaTypeId<QQmlScriptString>()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
if (!QMetaType::typeName(property->propType))
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
- } else if (value.asFunctionObject()) {
+ } else if (value.as<FunctionObject>()) {
// this is handled by the binding creation above
} else if (property->propType == QMetaType::Int && value.isNumber()) {
PROPERTY_STORE(int, value.asDouble());
@@ -548,11 +549,11 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else {
QVariant v;
if (property->isQList())
- v = ctx->d()->engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ v = scope.engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = ctx->d()->engine->toVariant(value, property->propType);
+ v = scope.engine->toVariant(value, property->propType);
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
const char *valueType = 0;
if (v.userType() == QVariant::Invalid) valueType = "null";
@@ -566,7 +567,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QLatin1String(valueType) +
QLatin1String(" to ") +
QLatin1String(targetTypeName);
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
}
@@ -639,7 +640,7 @@ void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine)
engine->m_multiplyWrappedQObjects->mark(object, engine);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired)
{
if (QQmlData::wasDeleted(object))
return QV4::Encode::null();
@@ -651,10 +652,10 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return getProperty(object, ctx, property, captureRequired);
+ return getProperty(engine, object, property, captureRequired);
}
-void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value)
{
if (QQmlData::wasDeleted(d()->object))
return;
@@ -666,14 +667,14 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return setProperty(d()->object, ctx, property, value);
+ return setProperty(engine, d()->object, property, value);
}
bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QV4::QObjectWrapper>());
QV4::QObjectWrapper *qobjectWrapper = static_cast<QV4::QObjectWrapper *>(a);
- QV4::Object *o = b->asObject();
+ QV4::Object *o = b->as<Object>();
if (o) {
if (QV4::QmlTypeWrapper *qmlTypeWrapper = o->as<QV4::QmlTypeWrapper>())
return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object();
@@ -689,10 +690,10 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue();
}
-QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty)
+QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
- QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(that->engine());
+ const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
+ QQmlContextData *qmlContext = that->engine()->callingQmlContext();
return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
@@ -704,7 +705,7 @@ void QObjectWrapper::put(Managed *m, String *name, const Value &value)
if (v4->hasException || QQmlData::wasDeleted(that->d()->object))
return;
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
+ QQmlContextData *qmlContext = v4->callingQmlContext();
if (!setQmlProperty(v4, qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object);
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
@@ -723,10 +724,10 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
{
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
ExecutionEngine *engine = that->engine();
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(engine);
+ QQmlContextData *qmlContext = engine->callingQmlContext();
QQmlPropertyData local;
if (that->findProperty(engine, qmlContext, name, IgnoreRevision, &local)
- || name->equals(engine->id_destroy) || name->equals(engine->id_toString))
+ || name->equals(engine->id_destroy()) || name->equals(engine->id_toString()))
return QV4::Attr_Data;
else
return QV4::Object::query(m, name);
@@ -750,7 +751,6 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject;
const int propertyCount = mo->propertyCount();
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
- // #### GC
Scope scope(that->engine());
ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
*name = propName->d();
@@ -766,7 +766,6 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
++it->arrayIndex;
if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
- // #### GC
Scope scope(that->engine());
ScopedString methodName(scope, that->engine()->newString(QString::fromUtf8(method.name())));
*name = methodName->d();
@@ -816,7 +815,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ScopedFunctionObject f(scope, This->function.value());
QV4::ScopedCallData callData(scope, argCount);
- callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject()->asReturnedValue() : This->thisObject.value();
+ callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
@@ -1234,7 +1233,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asDateObject()) {
+ } else if (actual.as<DateObject>()) {
switch (conversionType) {
case QMetaType::QDateTime:
return 0;
@@ -1252,7 +1251,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asArrayObject()) {
+ } else if (actual.as<ArrayObject>()) {
switch (conversionType) {
case QMetaType::QJsonArray:
return 3;
@@ -1281,7 +1280,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
return 10;
}
}
- } else if (QV4::Object *obj = actual.asObject()) {
+ } else if (const Object *obj = actual.as<Object>()) {
if (obj->as<QV4::VariantObject>()) {
if (conversionType == qMetaTypeId<QVariant>())
return 0;
@@ -1611,9 +1610,9 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == QMetaType::QObjectStar) {
qobjectPtr = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
- else if (QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
+ else if (const QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
queryEngine = qmlTypeWrapper->isSingleton();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
@@ -1635,7 +1634,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
}
} else {
QObject *o = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
o = qobjectWrapper->object();
qlistPtr->append(o);
}
@@ -1759,14 +1758,14 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in
return method.asReturnedValue();
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal)
+ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal)
{
Scope valueScope(scope);
Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
method->d()->propertyCache = valueType->d()->propertyCache;
method->d()->index = index;
method->d()->qmlGlobal = qmlGlobal;
- method->d()->valueTypeWrapper = valueType;
+ method->d()->valueTypeWrapper = *valueType;
return method.asReturnedValue();
}
@@ -1782,7 +1781,7 @@ const QMetaObject *Heap::QObjectMethod::metaObject()
return object->metaObject();
}
-QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
+QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const
{
QString result;
if (const QMetaObject *metaObject = d()->metaObject()) {
@@ -1808,7 +1807,7 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
return ctx->d()->engine->newString(result)->asReturnedValue();
}
-QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
+QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const
{
if (!d()->object)
return Encode::undefined();
@@ -1827,13 +1826,13 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con
return Encode::undefined();
}
-ReturnedValue QObjectMethod::call(Managed *m, CallData *callData)
+ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
{
- QObjectMethod *This = static_cast<QObjectMethod*>(m);
+ const QObjectMethod *This = static_cast<const QObjectMethod*>(m);
return This->callInternal(callData);
}
-ReturnedValue QObjectMethod::callInternal(CallData *callData)
+ReturnedValue QObjectMethod::callInternal(CallData *callData) const
{
Scope scope(engine());
ScopedContext context(scope, scope.engine->currentContext());
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 24e8b29e08..324f598ad9 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -54,7 +54,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qintrusivelist_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -104,7 +104,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
QObject *object() const { return d()->object.data(); }
- ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
+ ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false) const;
static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
@@ -114,21 +114,21 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
using Object::get;
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired);
- void setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired);
+ void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value);
protected:
static bool isEqualTo(Managed *that, Managed *o);
private:
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
- static void setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired = true);
+ static void setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value);
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
@@ -149,17 +149,17 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
enum { DestroyMethod = -1, ToStringMethod = -2 };
static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal = Primitive::undefinedValue());
- static ReturnedValue create(QV4::ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue());
+ static ReturnedValue create(QV4::ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue());
int methodIndex() const { return d()->index; }
QObject *object() const { return d()->object.data(); }
- QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx);
- QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
+ QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx) const;
+ QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const;
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
- ReturnedValue callInternal(CallData *callData);
+ ReturnedValue callInternal(CallData *callData) const;
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 8e18a5fbdd..31fee534ad 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -34,16 +34,16 @@
#include "qv4regexp_p.h"
#include "qv4engine_p.h"
#include "qv4scopedvalue_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
using namespace QV4;
RegExpCache::~RegExpCache()
{
- for (RegExpCache::Iterator it = begin(), e = end();
- it != e; ++it)
- it.value()->cache = 0;
- clear();
+ for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) {
+ if (RegExp *re = it.value().as<RegExp>())
+ re->d()->cache = 0;
+ }
}
DEFINE_MANAGED_VTABLE(RegExp);
@@ -68,19 +68,18 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
RegExpCacheKey key(pattern, ignoreCase, multiline);
RegExpCache *cache = engine->regExpCache;
- if (cache) {
- if (Heap::RegExp *result = cache->value(key))
- return result;
- }
+ if (!cache)
+ cache = engine->regExpCache = new RegExpCache;
+
+ QV4::WeakValue &cachedValue = (*cache)[key];
+ if (QV4::RegExp *result = cachedValue.as<RegExp>())
+ return result->d();
Scope scope(engine);
Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline));
- if (!cache)
- cache = engine->regExpCache = new RegExpCache;
-
result->d()->cache = cache;
- cache->insert(key, result->d());
+ cachedValue.set(engine, result);
return result->d();
}
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 819e31e5f1..af6e346ea8 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -133,8 +133,7 @@ inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW
{ return qHash(key.pattern, seed); }
-// ### GC
-class RegExpCache : public QHash<RegExpCacheKey, Heap::RegExp*>
+class RegExpCache : public QHash<RegExpCacheKey, WeakValue>
{
public:
~RegExpCache();
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index f6e88e62b7..329e5d2c56 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4regexp_p.h"
#include "qv4stringobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -75,7 +75,7 @@ Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype)
}
Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->regExpPrototype())
, value(value->d())
, global(global)
{
@@ -88,7 +88,7 @@ Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *valu
// The conversion is not 100% exact since ECMA regexp and QRegExp
// have different semantics/flags, but we try to do our best.
Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->regExpPrototype())
{
value = 0;
global = false;
@@ -174,7 +174,7 @@ void RegExpObject::markObjects(Heap::Base *that, ExecutionEngine *e)
Property *RegExpObject::lastIndexProperty()
{
- Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex));
+ Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
return propertyAt(0);
}
@@ -231,14 +231,14 @@ Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope)
void Heap::RegExpCtor::clearLastMatch()
{
lastMatch = Primitive::nullValue();
- lastInput = internalClass->engine->id_empty;
+ lastInput = internalClass->engine->id_empty()->d();
lastMatchStart = 0;
lastMatchEnd = 0;
}
-ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
ScopedContext ctx(scope, scope.engine->currentContext());
ScopedValue r(scope, callData->argument(0));
@@ -286,7 +286,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
return Encode(ctx->d()->engine->newRegExpObject(regexp, global));
}
-ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
+ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData)
{
if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
if (callData->argc == 1 || callData->args[1].isUndefined())
@@ -300,7 +300,7 @@ void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e)
{
RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that);
This->lastMatch.mark(e);
- This->lastInput.mark(e);
+ This->lastInput->mark(e);
FunctionObject::markObjects(that, e);
}
@@ -310,8 +310,8 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
ScopedObject o(scope);
ScopedObject ctor(scope, constructor);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(2));
// Properties deprecated in the spec but required by "the web" :(
ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0);
@@ -337,7 +337,7 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("compile"), method_compile, 2);
}
@@ -363,7 +363,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint));
const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
regExpCtor->d()->clearLastMatch();
if (result == -1) {
@@ -372,7 +372,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
}
// fill in result data
- ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype.asObject()));
+ ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype()));
int len = r->value()->captureCount();
array->arrayReserve(len);
ScopedValue v(scope);
@@ -388,7 +388,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
RegExpCtor::Data *dd = regExpCtor->d();
dd->lastMatch = array;
- dd->lastInput = arg->stringValue();
+ dd->lastInput = arg->stringValue()->d();
dd->lastMatchStart = matchOffsets[0];
dd->lastMatchEnd = matchOffsets[1];
@@ -425,7 +425,7 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
ScopedCallData callData(scope, ctx->argc());
memcpy(callData->args, ctx->args(), ctx->argc()*sizeof(Value));
- Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData));
+ Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor()->as<FunctionObject>()->construct(callData));
r->d()->value = re->value();
r->d()->global = re->global();
@@ -436,7 +436,7 @@ template <int index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -446,7 +446,7 @@ ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -455,13 +455,13 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
{
- return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastInput().asReturnedValue();
+ return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastInput()->asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue();
}
@@ -469,7 +469,7 @@ ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index f5f255faf5..29d20614de 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -61,14 +61,14 @@ struct RegExpObject : Object {
RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global);
RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re);
- RegExp *value;
+ Pointer<RegExp> value;
bool global;
};
struct RegExpCtor : FunctionObject {
RegExpCtor(QV4::ExecutionContext *scope);
Value lastMatch;
- StringValue lastInput;
+ Pointer<String> lastInput;
int lastMatchStart;
int lastMatchEnd;
void clearLastMatch();
@@ -117,12 +117,12 @@ struct RegExpCtor: FunctionObject
V4_OBJECT2(RegExpCtor, FunctionObject)
Value lastMatch() { return d()->lastMatch; }
- StringValue lastInput() { return d()->lastInput; }
+ Heap::String *lastInput() { return d()->lastInput; }
int lastMatchStart() { return d()->lastMatchStart; }
int lastMatchEnd() { return d()->lastMatchEnd; }
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -146,7 +146,7 @@ struct RegExpPrototype: RegExpObject
};
inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e)
- : RegExpObject(e->emptyClass, e->objectPrototype.asObject())
+ : RegExpObject(e->emptyClass, e->objectPrototype())
{
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index c31de6a9f0..3006ec9fe5 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -40,6 +40,7 @@
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4dateobject_p.h"
#include "qv4lookup_p.h"
#include "qv4function_p.h"
#include "private/qlocale_tools_p.h"
@@ -313,14 +314,14 @@ ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex)
QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right)
{
Scope scope(engine);
- ScopedFunctionObject f(scope, right.asFunctionObject());
+ ScopedFunctionObject f(scope, right.as<FunctionObject>());
if (!f)
return engine->throwTypeError();
if (f->isBoundFunction())
f = static_cast<BoundFunction *>(f.getPointer())->target();
- ScopedObject v(scope, left.asObject());
+ ScopedObject v(scope, left.as<Object>());
if (!v)
return Encode(false);
@@ -380,10 +381,10 @@ Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double n
return engine->newString(qstr);
}
-ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
+ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeHint)
{
if (typeHint == PREFERREDTYPE_HINT) {
- if (object->asDateObject())
+ if (object->as<DateObject>())
typeHint = STRING_HINT;
else
typeHint = NUMBER_HINT;
@@ -393,18 +394,18 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- StringValue *meth1 = &engine->id_toString;
- StringValue *meth2 = &engine->id_valueOf;
+ String *meth1 = engine->id_toString();
+ String *meth2 = engine->id_valueOf();
if (typeHint == NUMBER_HINT)
qSwap(meth1, meth2);
Scope scope(engine);
ScopedCallData callData(scope, 0);
- callData->thisObject = object;
+ callData->thisObject = *object;
- ScopedValue conv(scope, object->get(*meth1));
- if (FunctionObject *o = conv->asFunctionObject()) {
+ ScopedValue conv(scope, object->get(meth1));
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -413,8 +414,8 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- conv = object->get(*meth2);
- if (FunctionObject *o = conv->asFunctionObject()) {
+ conv = object->get(meth2);
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -437,7 +438,7 @@ Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Val
return engine->newBooleanObject(value.booleanValue());
case Value::Managed_Type:
Q_ASSERT(value.isString());
- return engine->newStringObject(value);
+ return engine->newStringObject(value.stringValue());
case Value::Integer_Type:
default: // double
return engine->newNumberObject(value.asDouble());
@@ -450,14 +451,14 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -481,14 +482,14 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -575,7 +576,7 @@ ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object,
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -909,7 +910,7 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal
return engine->throwTypeError();
ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval))
+ if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval()))
return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true);
return o->call(callData);
@@ -931,7 +932,7 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
if (base)
callData->thisObject = base;
- FunctionObject *o = func->asFunctionObject();
+ FunctionObject *o = func->as<FunctionObject>();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
if (base)
@@ -940,7 +941,7 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
return engine->throwTypeError(msg);
}
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) {
+ if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) {
return static_cast<EvalFunction *>(o)->evalCall(callData, true);
}
@@ -1034,7 +1035,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int
if (scope.engine->hasException)
return Encode::undefined();
- Object *f = func->asObject();
+ Object *f = func->as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1043,7 +1044,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int
ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func, CallData *callData)
{
- Object *f = func.asObject();
+ const Object *f = func.as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1089,24 +1090,24 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value)
ScopedString res(scope);
switch (value.type()) {
case Value::Undefined_Type:
- res = engine->id_undefined;
+ res = engine->id_undefined();
break;
case Value::Null_Type:
- res = engine->id_object;
+ res = engine->id_object();
break;
case Value::Boolean_Type:
- res = engine->id_boolean;
+ res = engine->id_boolean();
break;
case Value::Managed_Type:
if (value.isString())
- res = engine->id_string;
- else if (value.objectValue()->asFunctionObject())
- res = engine->id_function;
+ res = engine->id_string();
+ else if (value.objectValue()->as<FunctionObject>())
+ res = engine->id_function();
else
- res = engine->id_object; // ### implementation-defined
+ res = engine->id_object(); // ### implementation-defined
break;
default:
- res = engine->id_number;
+ res = engine->id_number();
break;
}
return res.asReturnedValue();
@@ -1199,7 +1200,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
{
Scope scope(engine);
QV4::InternalClass *klass = engine->currentContext()->compilationUnit->runtimeClasses[classId];
- ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype.asObject()));
+ ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype()));
{
bool needSparseArray = arrayGetterSetterCountAndFlags >> 30;
@@ -1239,7 +1240,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(engine->currentContext()->type >= Heap::ExecutionContext::Type_CallContext);
+ Q_ASSERT(engine->currentContext()->type == Heap::ExecutionContext::Type_CallContext);
Scope scope(engine);
Scoped<CallContext> c(scope, static_cast<Heap::CallContext *>(engine->currentContext()));
return (engine->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue();
@@ -1334,14 +1335,12 @@ ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
ReturnedValue Runtime::getQmlIdArray(NoThrowEngine *engine)
{
Q_ASSERT(engine->qmlContextObject());
- Scope scope(engine);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->idObjectsArray();
+ return engine->qmlContextObject()->asReturnedValue();
}
ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
+ QQmlContextData *context = engine->callingQmlContext();
if (!context)
return Encode::undefined();
return QObjectWrapper::wrap(engine, context->contextObject);
@@ -1349,9 +1348,7 @@ ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine)
ReturnedValue Runtime::getQmlScopeObject(NoThrowEngine *engine)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- return QObjectWrapper::wrap(engine, c->getScopeObject());
+ return QObjectWrapper::wrap(engine, engine->qmlScopeObject());
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1362,21 +1359,17 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Valu
engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->object(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->object(), propertyIndex, captureRequired);
}
QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- QObject *scopeObject = c->getScopeObject();
+ QObject *scopeObject = engine->qmlScopeObject();
QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject);
QJSEngine *jsEngine = engine->jsEngine();
QQmlData::ensurePropertyCache(jsEngine, attachedObject);
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true);
+ return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true);
}
ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1387,8 +1380,7 @@ ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, c
scope.engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->singletonObject(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->singletonObject(), propertyIndex, captureRequired);
}
void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)
@@ -1399,13 +1391,12 @@ void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object
engine->throwTypeError(QStringLiteral("Cannot write property of null"));
return;
}
- ScopedContext ctx(scope, engine->currentContext());
- wrapper->setProperty(ctx, propertyIndex, value);
+ wrapper->setProperty(engine, propertyIndex, value);
}
ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
+ QQmlContextData *context = engine->callingQmlContext();
if (!context)
return Encode::undefined();
return context->importedScripts.value();
@@ -1425,7 +1416,7 @@ void Runtime::convertThisToObject(ExecutionEngine *engine)
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
- *t = engine->globalObject()->asReturnedValue();
+ *t = engine->globalObject->asReturnedValue();
} else {
*t = t->toObject(engine)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index f2f90bbc15..e8ebccc17b 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -34,8 +34,9 @@
#define QMLJS_RUNTIME_H
#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4context_p.h"
+#include "qv4engine_p.h"
#include "qv4math_p.h"
#include <QtCore/qnumeric.h>
@@ -218,7 +219,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
};
struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
- static ReturnedValue objectDefaultValue(Object *object, int typeHint);
+ static ReturnedValue objectDefaultValue(const Object *object, int typeHint);
static ReturnedValue toPrimitive(const Value &value, int typeHint);
static double stringToNumber(const QString &s);
@@ -243,7 +244,7 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
#ifndef V4_BOOTSTRAP
inline ReturnedValue RuntimeHelpers::toPrimitive(const Value &value, int typeHint)
{
- Object *o = value.asObject();
+ const Object *o = value.as<Object>();
if (!o)
return value.asReturnedValue();
return RuntimeHelpers::objectDefaultValue(o, typeHint);
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 908248f0f0..02b038f247 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -85,10 +85,7 @@ struct Scope {
#ifndef QT_NO_DEBUG
size += nValues;
#endif
- Value *ptr = engine->jsStackTop;
- engine->jsStackTop = ptr + nValues;
- memset(ptr, 0, nValues*sizeof(Value));
- return ptr;
+ return engine->jsAlloca(nValues);
}
bool hasException() const {
@@ -202,7 +199,7 @@ struct Scoped
{
enum _Convert { Convert };
- inline void setPointer(Managed *p) {
+ inline void setPointer(const Managed *p) {
ptr->m = p ? p->m : 0;
#if QT_POINTER_SIZE == 4
ptr->tag = QV4::Value::Managed_Type;
@@ -221,11 +218,10 @@ struct Scoped
#endif
}
- // ### GC FIX casting below to be safe
Scoped(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -235,7 +231,7 @@ struct Scoped
Value v;
v = o;
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -243,7 +239,7 @@ struct Scoped
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(*v.ptr));
+ setPointer(v.ptr->as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -261,7 +257,7 @@ struct Scoped
Scoped(const Scope &scope, const Value *v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(v ? value_cast<T>(*v) : 0);
+ setPointer(v ? v->as<T>() : 0);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -287,7 +283,7 @@ struct Scoped
Scoped(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -302,9 +298,7 @@ struct Scoped
}
Scoped<T> &operator=(Heap::Base *o) {
- Value v;
- v = o;
- setPointer(value_cast<T>(v));
+ setPointer(Value::fromHeapObject(o).as<T>());
return *this;
}
Scoped<T> &operator=(typename T::Data *t) {
@@ -312,16 +306,16 @@ struct Scoped
return *this;
}
Scoped<T> &operator=(const Value &v) {
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
return *this;
}
Scoped<T> &operator=(Value *v) {
- setPointer(v ? value_cast<T>(*v) : 0);
+ setPointer(v ? v->as<T>() : 0);
return *this;
}
Scoped<T> &operator=(const ReturnedValue &v) {
- setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
return *this;
}
@@ -401,33 +395,6 @@ inline Value &Value::operator=(const Scoped<T> &t)
return *this;
}
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(T *t)
-{
- m = t ? t->m : 0;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
-{
- m = v.ptr->m;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator=(const TypedValue<T> &t)
-{
- val = t.val;
- return *this;
-}
-
struct ScopedProperty
{
ScopedProperty(Scope &scope)
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 4fde0e2445..576488275e 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4script_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4functionobject_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
@@ -44,6 +44,7 @@
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4profiling_p.h>
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include <private/qqmlcontextwrapper_p.h>
@@ -86,8 +87,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
, qml(qml->d())
{
Q_ASSERT(scope->inUse());
@@ -97,46 +98,43 @@ Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Functio
function->compilationUnit->addref();
Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
+ Scoped<QV4::QmlBindingWrapper> protectThis(s, this);
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
-
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
+ this->scope = scope->newQmlContext(qml);
+ internalClass->engine->popContext();
}
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::QmlContextWrapper *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
, qml(qml->d())
{
Q_ASSERT(scope->inUse());
Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
-
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
+ Scoped<QV4::QmlBindingWrapper> protectThis(s, this);
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
+ this->scope = scope->newQmlContext(qml);
+ internalClass->engine->popContext();
}
-ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
+ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *engine = static_cast<Object *>(that)->engine();
- CHECK_STACK_LIMITS(engine);
+ const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that);
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
+ if (v4->hasException)
+ return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
- Scope scope(engine);
- QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
- if (!This->function())
+ Scope scope(v4);
+ QV4::Function *f = This->function();
+ if (!f)
return QV4::Encode::undefined();
- Scoped<CallContext> ctx(scope, This->d()->qmlContext);
- std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue());
- engine->pushContext(ctx);
- ScopedValue result(scope, This->function()->code(engine, This->function()->codeData));
- engine->popContext();
+ ScopedContext context(scope, v4->currentContext());
+ Scoped<CallContext> ctx(scope, context->newCallContext(This, callData));
+
+ ExecutionContextSaver ctxSaver(scope, context);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f));
return result->asReturnedValue();
}
@@ -147,14 +145,12 @@ void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e)
if (wrapper->qml)
wrapper->qml->mark(e);
FunctionObject::markObjects(m, e);
- if (wrapper->qmlContext)
- wrapper->qmlContext->mark(e);
}
static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
{
QV4::Scope scope(ctx);
- QV4::Scoped<CallContext> signalEmittingContext(scope, static_cast<Heap::CallContext *>(ctx->d()->parent));
+ QV4::Scoped<CallContext> signalEmittingContext(scope, ctx->d()->parent.cast<Heap::CallContext>());
Q_ASSERT(signalEmittingContext && signalEmittingContext->d()->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext);
return signalEmittingContext->argument(parameterIndex);
}
@@ -163,10 +159,10 @@ Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContex
{
ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
QV4::Scope valueScope(engine);
- QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
+ QV4::Scoped<QmlContextWrapper> qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
ScopedContext global(valueScope, valueScope.engine->rootContext());
QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScopeObject));
- QV4::Scoped<CallContext> wrapperContext(valueScope, wrapper->context());
+ QV4::Scoped<QmlContext> wrapperContext(valueScope, wrapper->context());
if (!signalParameters.isEmpty()) {
if (error)
@@ -214,7 +210,7 @@ void Script::parse()
parsed = true;
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -285,7 +281,7 @@ ReturnedValue Script::run()
if (!vmFunction)
return Encode::undefined();
- QV4::ExecutionEngine *engine = scope->engine;
+ QV4::ExecutionEngine *engine = scope->engine();
QV4::Scope valueScope(engine);
if (qml.isUndefined()) {
@@ -293,15 +289,14 @@ ReturnedValue Script::run()
ExecutionContextSaver ctxSaver(valueScope, scope);
ContextStateSaver stateSaver(valueScope, scope);
- scope->strictMode = vmFunction->isStrict();
- scope->lookups = vmFunction->compilationUnit->runtimeLookups;
- scope->compilationUnit = vmFunction->compilationUnit;
+ scope->d()->strictMode = vmFunction->isStrict();
+ scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
+ scope->d()->compilationUnit = vmFunction->compilationUnit;
return vmFunction->code(engine, vmFunction->codeData);
} else {
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
+ Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
+ ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
ScopedCallData callData(valueScope);
callData->thisObject = Primitive::undefinedValue();
return f->call(callData);
@@ -376,11 +371,10 @@ ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
+ Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
+ ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
return v.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 05a9e45f45..015bfff56a 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -87,11 +87,10 @@ struct ContextStateSaver {
namespace Heap {
struct QmlBindingWrapper : Heap::FunctionObject {
- QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml);
+ QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml);
// Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
- QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml);
- Object *qml;
- CallContext *qmlContext;
+ QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::QmlContextWrapper *qml);
+ Pointer<Object> qml;
};
}
@@ -99,21 +98,19 @@ struct QmlBindingWrapper : Heap::FunctionObject {
struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
V4_OBJECT2(QmlBindingWrapper, FunctionObject)
- static ReturnedValue call(Managed *that, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *m, ExecutionEngine *e);
- Heap::CallContext *context() const { return d()->qmlContext; }
+ Heap::QmlContext *context() const { return static_cast<Heap::QmlContext *>(d()->scope.ptr); }
static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
-
-private:
};
struct Q_QML_EXPORT Script {
Script(ExecutionContext *scope, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
- , scope(scope->d()), strictMode(false), inheritContext(false), parsed(false)
+ , scope(scope), strictMode(false), inheritContext(false), parsed(false)
, vmFunction(0), parseAsBinding(false) {}
Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
@@ -125,8 +122,7 @@ struct Q_QML_EXPORT Script {
int line;
int column;
QString sourceCode;
- // ### GC
- Heap::ExecutionContext *scope;
+ ExecutionContext *scope;
bool strictMode;
bool inheritContext;
bool parsed;
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index f1f546bece..4fba65d396 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -175,7 +175,7 @@ template <> QUrl convertValueToElement(const Value &value)
template <> QModelIndex convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().toModelIndex();
return QModelIndex();
@@ -183,7 +183,7 @@ template <> QModelIndex convertValueToElement(const Value &value)
template <> QItemSelectionRange convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().value<QItemSelectionRange>();
return QItemSelectionRange();
@@ -231,7 +231,7 @@ public:
defineAccessorProperty(QStringLiteral("length"), method_get_length, method_set_length);
}
- QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty)
+ QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty) const
{
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
@@ -400,7 +400,7 @@ public:
ScopedCallData callData(scope, 2);
callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs);
callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs);
- callData->thisObject = this->m_ctx->d()->engine->globalObject();
+ callData->thisObject = this->m_ctx->d()->engine->globalObject;
QV4::ScopedValue result(scope, compare->call(callData));
return result->toNumber() < 0;
}
@@ -419,7 +419,7 @@ public:
}
QV4::Scope scope(ctx);
- if (ctx->argc() == 1 && ctx->args()[0].asFunctionObject()) {
+ if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) {
CompareFunctor cf(ctx, ctx->args()[0]);
std::sort(d()->container.begin(), d()->container.end(), cf);
} else {
@@ -526,8 +526,8 @@ public:
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
- static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty)
- { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty)
+ { return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
static void putIndexed(Managed *that, uint index, const QV4::Value &value)
{ static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
@@ -544,7 +544,7 @@ public:
template <typename Container>
Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->sequencePrototype())
, container(container)
, propertyIndex(-1)
, isReference(false)
@@ -557,7 +557,7 @@ Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const
template <typename Container>
Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->sequencePrototype())
, object(object)
, propertyIndex(propertyIndex)
, isReference(true)
@@ -605,7 +605,7 @@ void SequencePrototype::init()
{
FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
defineDefaultProperty(QStringLiteral("sort"), method_sort, 1);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
}
#undef REGISTER_QML_SEQUENCE_METATYPE
@@ -700,11 +700,11 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
{
*succeeded = true;
- if (!array.asArrayObject()) {
+ if (!array.as<ArrayObject>()) {
*succeeded = false;
return QVariant();
}
- QV4::Scope scope(array.asObject()->engine());
+ QV4::Scope scope(array.as<Object>()->engine());
QV4::ScopedArrayObject a(scope, array);
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); }
@@ -717,7 +717,7 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
return qMetaTypeId<SequenceType>(); \
} else
-int SequencePrototype::metaTypeForSequence(QV4::Object *object)
+int SequencePrototype::metaTypeForSequence(const QV4::Object *object)
{
FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE)
/*else*/ {
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 9949278a89..560c3c27ca 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -48,9 +48,10 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4object_p.h"
#include "qv4context_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -70,7 +71,7 @@ struct SequencePrototype : public QV4::Object
static bool isSequenceType(int sequenceTypeId);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
- static int metaTypeForSequence(Object *object);
+ static int metaTypeForSequence(const Object *object);
static QVariant toVariant(Object *object);
static QVariant toVariant(const Value &array, int typeHint, bool *succeeded);
};
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index e669924d4a..090e9c7e6a 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -37,7 +37,7 @@
#include <private/qqmllistmodel_p.h>
#include <private/qqmllistmodelworkeragent_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qv4sequenceobject_p.h>
@@ -168,11 +168,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, qstr.constData(), length*sizeof(QChar));
- } else if (v.asFunctionObject()) {
+ } else if (v.as<FunctionObject>()) {
// XXX TODO: Implement passing function objects between the main and
// worker scripts
push(data, valueheader(WorkerUndefined));
- } else if (QV4::ArrayObject *array = v.asArrayObject()) {
+ } else if (const QV4::ArrayObject *array = v.as<ArrayObject>()) {
uint length = array->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -195,11 +195,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerNumber));
push(data, v.asDouble());
- } else if (QV4::DateObject *d = v.asDateObject()) {
+ } else if (const QV4::DateObject *d = v.as<DateObject>()) {
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerDate));
- push(data, d->date().asDouble());
- } else if (RegExpObject *re = v.as<RegExpObject>()) {
+ push(data, d->date());
+ } else if (const RegExpObject *re = v.as<RegExpObject>()) {
quint32 flags = re->flags();
QString pattern = re->source();
int length = pattern.length() + 1;
@@ -218,7 +218,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, pattern.constData(), length*sizeof(QChar));
- } else if (QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
+ } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
// XXX TODO: Generalize passing objects between the main thread and worker scripts so
// that others can trivially plug in their elements.
QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
@@ -231,10 +231,10 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
}
// No other QObject's are allowed to be sent
push(data, valueheader(WorkerUndefined));
- } else if (Object *o = v.asObject()) {
+ } else if (const Object *o = v.as<Object>()) {
if (o->isListType()) {
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint seqLength = ScopedValue(scope, o->get(engine->id_length))->toUInt32();
+ uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32();
uint length = seqLength + 1;
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -265,7 +265,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
s = properties->getIndexed(ii);
serialize(data, s, engine);
- QV4::String *str = s->asString();
+ QV4::String *str = s->as<String>();
val = o->get(str);
if (scope.hasException())
scope.engine->catchException();
@@ -356,7 +356,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
QVariant var = qVariantFromValue(ref);
QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref")));
- rv->asObject()->defineReadonlyProperty(s, v);
+ rv->as<Object>()->defineReadonlyProperty(s, v);
agent->release();
agent->setEngine(engine);
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h
index 06eaffe4c4..d5d48edee7 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4serialize_p.h
@@ -46,7 +46,7 @@
//
#include <QtCore/qbytearray.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 861c7dd28d..8496fc32e7 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -35,11 +35,7 @@
#define QV4SPARSEARRAY_H
#include "qv4global_p.h"
-#include <QtCore/qmap.h>
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
-#include "qv4property_p.h"
-#include <assert.h>
+#include <QtCore/qlist.h>
//#define Q_MAP_DEBUG
#ifdef Q_MAP_DEBUG
@@ -188,7 +184,7 @@ public:
typedef qptrdiff difference_type;
typedef int size_type;
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
void dump() const;
#endif
};
@@ -261,7 +257,7 @@ inline void SparseArray::push_back(uint index, uint len)
n->value = index;
}
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
inline void SparseArray::dump() const
{
const SparseArrayNode *it = begin();
@@ -344,4 +340,4 @@ inline SparseArrayNode *SparseArray::upperBound(uint akey)
QT_END_NAMESPACE
-#endif // QMAP_H
+#endif
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 20dd84420c..cf013121b1 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#ifndef V4_BOOTSTRAP
#include "qv4identifiertable_p.h"
#include "qv4runtime_p.h"
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 5a0c83b4b9..b133f68b20 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -184,6 +184,20 @@ public:
static uint toArrayIndex(const QString &str);
};
+template<>
+inline const String *Value::as() const {
+ return isManaged() && m && m->vtable->isString ? static_cast<const String *>(this) : 0;
+}
+
+#ifndef V4_BOOTSTRAP
+template<>
+inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
+{
+ return v.toString(e)->asReturnedValue();
+}
+#endif
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index e0b84f6da3..402ab420fc 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -36,7 +36,7 @@
#include "qv4regexp_p.h"
#include "qv4regexpobject_p.h"
#include "qv4objectproto_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4alloca_p.h"
#include <QtCore/QDateTime>
@@ -71,43 +71,44 @@ Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype)
: Heap::Object(ic, prototype)
{
Q_ASSERT(vtable == QV4::StringObject::staticVTable());
- value = ic->engine->newString()->asReturnedValue();
- tmpProperty.value = Primitive::undefinedValue();
+ string = ic->engine->newString();
Scope scope(ic->engine);
ScopedObject s(scope, this);
- s->defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0));
+ s->defineReadonlyProperty(ic->engine->id_length(), Primitive::fromInt32(0));
}
-Heap::StringObject::StringObject(ExecutionEngine *engine, const Value &val)
- : Heap::Object(engine->emptyClass, engine->stringPrototype.asObject())
+Heap::StringObject::StringObject(ExecutionEngine *engine, const QV4::String *str)
+ : Heap::Object(engine->emptyClass, engine->stringPrototype())
{
- value = val;
- Q_ASSERT(value.isString());
- tmpProperty.value = Primitive::undefinedValue();
+ string = str->d();
Scope scope(engine);
ScopedObject s(scope, this);
- s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length()));
+ s->defineReadonlyProperty(engine->id_length(), Primitive::fromUInt32(length()));
}
-Property *Heap::StringObject::getIndex(uint index) const
+Heap::String *Heap::StringObject::getIndex(uint index) const
{
- QString str = value.stringValue()->toQString();
+ QString str = string->toQString();
if (index >= (uint)str.length())
return 0;
- tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1)));
- return &tmpProperty;
+ return internalClass->engine->newString(str.mid(index, 1));
+}
+
+uint Heap::StringObject::length() const
+{
+ return string->toQString().length();
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
{
ExecutionEngine *v4 = static_cast<StringObject *>(m)->engine();
Scope scope(v4);
- Scoped<StringObject> o(scope, m->asStringObject());
+ Scoped<StringObject> o(scope, m->as<StringObject>());
Q_ASSERT(!!o);
- if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) {
+ if (index < static_cast<uint>(o->d()->string->toQString().length())) {
if (v4->currentContext()->strictMode)
v4->throwTypeError();
return false;
@@ -119,16 +120,17 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String
{
*name = (Heap::String *)0;
StringObject *s = static_cast<StringObject *>(m);
- uint slen = s->d()->value.stringValue()->toQString().length();
+ uint slen = s->d()->string->toQString().length();
if (it->arrayIndex <= slen) {
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
PropertyAttributes a;
- Property *pd = s->__getOwnProperty__(*index, &a);
+ Property pd;
+ s->getOwnProperty(*index, &a, &pd);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
- p->copy(pd, a);
+ p->copy(&pd, a);
return;
}
}
@@ -146,8 +148,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String
void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
StringObject::Data *o = static_cast<StringObject::Data *>(that);
- o->value.stringValue()->mark(e);
- o->tmpProperty.value.mark(e);
+ o->string->mark(e);
Object::markObjects(that, e);
}
@@ -158,11 +159,11 @@ Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
+ReturnedValue StringCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
- ScopedValue value(scope);
+ ScopedString value(scope);
if (callData->argc)
value = callData->args[0].toString(v4);
else
@@ -170,9 +171,9 @@ ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
return Encode(v4->newStringObject(value));
}
-ReturnedValue StringCtor::call(Managed *m, CallData *callData)
+ReturnedValue StringCtor::call(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue value(scope);
if (callData->argc)
@@ -187,13 +188,13 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("fromCharCode"), method_fromCharCode, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_toString); // valueOf and toString are identical
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_toString); // valueOf and toString are identical
defineDefaultProperty(QStringLiteral("charAt"), method_charAt, 1);
defineDefaultProperty(QStringLiteral("charCodeAt"), method_charCodeAt, 1);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
@@ -220,8 +221,8 @@ static QString getThisString(ExecutionContext *ctx)
ScopedValue t(scope, ctx->thisObject());
if (t->isString())
return t->stringValue()->toQString();
- if (StringObject *thisString = t->asStringObject())
- return thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = t->as<StringObject>())
+ return thisString->d()->string->toQString();
if (t->isUndefined() || t->isNull()) {
scope.engine->throwTypeError();
return QString();
@@ -234,10 +235,10 @@ ReturnedValue StringPrototype::method_toString(CallContext *context)
if (context->thisObject().isString())
return context->thisObject().asReturnedValue();
- StringObject *o = context->thisObject().asStringObject();
+ StringObject *o = context->thisObject().as<StringObject>();
if (!o)
return context->engine()->throwTypeError();
- return o->d()->value.asReturnedValue();
+ return Encode(o->d()->string);
}
ReturnedValue StringPrototype::method_charAt(CallContext *context)
@@ -368,7 +369,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (!rx) {
ScopedCallData callData(scope, 1);
callData->args[0] = regexp;
- rx = context->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ rx = context->d()->engine->regExpCtor()->construct(callData);
}
if (!rx)
@@ -379,7 +380,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
// ### use the standard builtin function, not the one that might be redefined in the proto
ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec")));
- ScopedFunctionObject exec(scope, scope.engine->regExpPrototype.asObject()->get(execString));
+ ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString));
ScopedCallData callData(scope, 1);
callData->thisObject = rx;
@@ -470,8 +471,8 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
{
Scope scope(ctx);
QString string;
- if (StringObject *thisString = ctx->thisObject().asStringObject())
- string = thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = ctx->thisObject().as<StringObject>())
+ string = thisString->d()->string->toQString();
else
string = ctx->thisObject().toQString();
@@ -481,12 +482,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint allocatedMatchOffsets = 64;
uint _matchOffsets[64];
uint *matchOffsets = _matchOffsets;
- uint nMatchOffsets = 0;
ScopedValue searchValue(scope, ctx->argument(0));
Scoped<RegExpObject> regExp(scope, searchValue);
if (regExp) {
uint offset = 0;
+ uint nMatchOffsets = 0;
// We extract the pointer here to work around a compiler bug on Android.
Scoped<RegExp> re(scope, regExp->value());
@@ -519,7 +520,6 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
int idx = string.indexOf(searchString);
if (idx != -1) {
numStringMatches = 1;
- nMatchOffsets = 2;
matchOffsets[0] = idx;
matchOffsets[1] = idx + searchString.length();
}
@@ -593,7 +593,7 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
if (!regExp) {
ScopedCallData callData(scope, 1);
callData->args[0] = regExpValue;
- regExpValue = ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ regExpValue = ctx->d()->engine->regExpCtor()->construct(callData);
if (scope.engine->hasException)
return Encode::undefined();
regExp = regExpValue->as<RegExpObject>();
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 459dc1322e..709b73f0bb 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -45,12 +45,11 @@ namespace Heap {
struct StringObject : Object {
StringObject(InternalClass *ic, QV4::Object *prototype);
- StringObject(ExecutionEngine *engine, const Value &value);
- Value value;
+ StringObject(ExecutionEngine *engine, const QV4::String *string);
+ String *string;
- Property *getIndex(uint index) const;
- // ### get rid of tmpProperty
- mutable Property tmpProperty;
+ Heap::String *getIndex(uint index) const;
+ uint length() const;
};
struct StringCtor : FunctionObject {
@@ -63,9 +62,12 @@ struct StringObject: Object {
V4_OBJECT2(StringObject, Object)
Q_MANAGED_TYPE(StringObject)
- Property *getIndex(uint index) const {
+ Heap::String *getIndex(uint index) const {
return d()->getIndex(index);
}
+ uint length() const {
+ return d()->length();
+ }
static bool deleteIndexedProperty(Managed *m, uint index);
@@ -78,8 +80,8 @@ struct StringCtor: FunctionObject
{
V4_OBJECT2(StringCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct StringPrototype: StringObject
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 429ec96f0b..f5b81fb6f7 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4typedarray_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include <cmath>
@@ -201,10 +202,10 @@ Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::T
{
}
-ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArrayCtor> that(scope, static_cast<TypedArrayCtor *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArrayCtor> that(scope, static_cast<const TypedArrayCtor *>(m));
if (!callData->argc || !callData->args[0].isObject()) {
// ECMA 6 22.2.1.1
@@ -299,7 +300,7 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
// ECMA 6 22.2.1.3
ScopedObject o(scope, callData->argument(0));
- uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length))->toInteger(), (double)UINT_MAX);
+ uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length()))->toInteger(), (double)UINT_MAX);
if (scope.engine->hasException)
return scope.engine->throwTypeError();
@@ -329,13 +330,13 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
return array.asReturnedValue();
}
-ReturnedValue TypedArrayCtor::call(Managed *that, CallData *callData)
+ReturnedValue TypedArrayCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
Heap::TypedArray::TypedArray(ExecutionEngine *e, Type t)
- : Heap::Object(e->emptyClass, e->typedArrayPrototype[t].asObject()),
+ : Heap::Object(e->emptyClass, e->typedArrayPrototype + t),
type(operations + t),
arrayType(t)
{
@@ -347,10 +348,10 @@ void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e)
Object::markObjects(that, e);
}
-ReturnedValue TypedArray::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
@@ -390,10 +391,10 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
@@ -470,7 +471,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
if (scope.engine->hasException || !o)
return scope.engine->throwTypeError();
- double len = ScopedValue(scope, o->get(scope.engine->id_length))->toNumber();
+ double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber();
uint l = (uint)len;
if (scope.engine->hasException || l != len)
return scope.engine->throwTypeError();
@@ -563,7 +564,7 @@ ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx)
int newLen = end - begin;
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index afd1bb97e7..8e1090dcd2 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -72,7 +72,7 @@ struct TypedArray : Object {
TypedArray(ExecutionEngine *e, Type t);
const TypedArrayOperations *type;
- ArrayBuffer *buffer;
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
Type arrayType;
@@ -113,7 +113,7 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
}
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
};
@@ -121,8 +121,8 @@ struct TypedArrayCtor: FunctionObject
{
V4_OBJECT2(TypedArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 68228f06bb..d659d02c3b 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -32,10 +32,11 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4runtime_p.h>
+#include <qv4string_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#endif
#include <wtf/MathExtras.h>
@@ -68,6 +69,28 @@ int Value::toUInt16() const
return (unsigned short)number;
}
+bool Value::toBoolean() const
+{
+ switch (type()) {
+ case Value::Undefined_Type:
+ case Value::Null_Type:
+ return false;
+ case Value::Boolean_Type:
+ case Value::Integer_Type:
+ return (bool)int_32;
+ case Value::Managed_Type:
+#ifdef V4_BOOTSTRAP
+ Q_UNIMPLEMENTED();
+#else
+ if (isString())
+ return stringValue()->toQString().length() > 0;
+#endif
+ return true;
+ default: // double
+ return doubleValue() && !std::isnan(doubleValue());
+ }
+}
+
double Value::toInteger() const
{
if (integerCompatible())
@@ -87,10 +110,10 @@ double Value::toNumberImpl() const
#else
if (isString())
return RuntimeHelpers::stringToNumber(stringValue()->toQString());
- {
- Q_ASSERT(isObject());
- Scope scope(objectValue()->engine());
- ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
+ {
+ Q_ASSERT(isObject());
+ Scope scope(objectValue()->engine());
+ ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
if (scope.engine->hasException)
return 0;
return prim->toNumber();
@@ -281,4 +304,35 @@ Heap::Object *Value::toObject(ExecutionEngine *e) const
return RuntimeHelpers::convertToObject(e, *this);
}
+uint Value::asArrayLength(bool *ok) const
+{
+ *ok = true;
+ if (isInteger()) {
+ if (int_32 >= 0) {
+ return (uint)int_32;
+ } else {
+ *ok = false;
+ return UINT_MAX;
+ }
+ }
+ if (isNumber()) {
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+ }
+ if (isString())
+ return stringValue()->toUInt(ok);
+
+ uint idx = toUInt32();
+ double d = toNumber();
+ if (d != idx) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h
deleted file mode 100644
index 3a4c5c4822..0000000000
--- a/src/qml/jsruntime/qv4value_inl_p.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QV4VALUE_INL_H
-#define QV4VALUE_INL_H
-
-#include <cmath> // this HAS to come
-
-#include "qv4value_p.h"
-
-#include "qv4string_p.h"
-#include "qv4managed_p.h"
-#include "qv4engine_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-inline bool Value::isString() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isString;
-}
-inline bool Value::isObject() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isObject;
-}
-
-inline bool Value::isPrimitive() const
-{
- return !isObject();
-}
-
-inline String *Value::asString() const
-{
- if (isString())
- return stringValue();
- return 0;
-}
-
-inline void Value::mark(ExecutionEngine *e) const
-{
- if (!val)
- return;
- Managed *m = asManaged();
- if (m)
- m->mark(e);
-}
-
-inline Primitive Primitive::nullValue()
-{
- Primitive v;
-#if QT_POINTER_SIZE == 8
- v.val = quint64(_Null_Type) << Tag_Shift;
-#else
- v.tag = _Null_Type;
- v.int_32 = 0;
-#endif
- return v;
-}
-
-inline Primitive Primitive::fromBoolean(bool b)
-{
- Primitive v;
- v.tag = _Boolean_Type;
- v.int_32 = (bool)b;
- return v;
-}
-
-inline Primitive Primitive::fromDouble(double d)
-{
- Primitive v;
- v.setDouble(d);
- return v;
-}
-
-inline Primitive Primitive::fromInt32(int i)
-{
- Primitive v;
- v.tag = _Integer_Type;
- v.int_32 = i;
- return v;
-}
-
-inline Primitive Primitive::fromUInt32(uint i)
-{
- Primitive v;
- if (i < INT_MAX) {
- v.tag = _Integer_Type;
- v.int_32 = (int)i;
- } else {
- v.setDouble(i);
- }
- return v;
-}
-
-inline double Value::toNumber() const
-{
- if (isInteger())
- return int_32;
- if (isDouble())
- return doubleValue();
- return toNumberImpl();
-}
-
-inline int Value::toInt32() const
-{
- if (isInteger())
- return int_32;
- double d = isNumber() ? doubleValue() : toNumberImpl();
-
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
-
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
-
- return Primitive::toInt32(d);
-}
-
-inline unsigned int Value::toUInt32() const
-{
- return (unsigned int)toInt32();
-}
-
-
-inline bool Value::toBoolean() const
-{
- switch (type()) {
- case Value::Undefined_Type:
- case Value::Null_Type:
- return false;
- case Value::Boolean_Type:
- case Value::Integer_Type:
- return (bool)int_32;
- case Value::Managed_Type:
-#ifdef V4_BOOTSTRAP
- Q_UNIMPLEMENTED();
-#else
- if (isString())
- return stringValue()->toQString().length() > 0;
-#endif
- return true;
- default: // double
- return doubleValue() && !std::isnan(doubleValue());
- }
-}
-
-#ifndef V4_BOOTSTRAP
-inline uint Value::asArrayIndex() const
-{
-#if QT_POINTER_SIZE == 8
- if (!isNumber())
- return UINT_MAX;
- if (isInteger())
- return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
-#else
- if (isInteger() && int_32 >= 0)
- return (uint)int_32;
- if (!isDouble())
- return UINT_MAX;
-#endif
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d)
- return UINT_MAX;
- return idx;
-}
-
-inline uint Value::asArrayLength(bool *ok) const
-{
- *ok = true;
- if (isInteger()) {
- if (int_32 >= 0) {
- return (uint)int_32;
- } else {
- *ok = false;
- return UINT_MAX;
- }
- }
- if (isNumber()) {
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
- }
- if (isString())
- return stringValue()->toUInt(ok);
-
- uint idx = toUInt32();
- double d = toNumber();
- if (d != idx) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
-}
-
-inline Object *Value::asObject() const
-{
- return isObject() ? objectValue() : 0;
-}
-
-inline FunctionObject *Value::asFunctionObject() const
-{
- return isObject() ? managed()->asFunctionObject() : 0;
-}
-
-inline NumberObject *Value::asNumberObject() const
-{
- return isObject() ? managed()->asNumberObject() : 0;
-}
-
-inline StringObject *Value::asStringObject() const
-{
- return isObject() ? managed()->asStringObject() : 0;
-}
-
-inline DateObject *Value::asDateObject() const
-{
- return isObject() ? managed()->asDateObject() : 0;
-}
-
-inline ArrayObject *Value::asArrayObject() const
-{
- return isObject() ? managed()->asArrayObject() : 0;
-}
-
-inline ErrorObject *Value::asErrorObject() const
-{
- return isObject() ? managed()->asErrorObject() : 0;
-}
-
-template<typename T>
-inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
-
-#ifndef V4_BOOTSTRAP
-
-template<>
-inline String *value_cast(const Value &v) {
- return v.asString();
-}
-
-template<>
-inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
-{
- return v.toString(e)->asReturnedValue();
-}
-
-#endif
-
-#endif
-
-} // namespace QV4
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index cd1aef86d7..7454cbfff4 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -37,61 +37,18 @@
#include <QtCore/QString>
#include "qv4global_p.h"
+#include <private/qv4heap_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-typedef uint Bool;
-
namespace Heap {
-
-struct Q_QML_EXPORT Base {
- union {
- const ManagedVTable *vtable;
- quintptr mm_data;
- };
-
- inline ReturnedValue asReturnedValue() const;
- inline void mark(QV4::ExecutionEngine *engine);
-
- enum {
- MarkBit = 0x1,
- NotInUse = 0x2,
- PointerMask = ~0x3
- };
-
- ManagedVTable *gcGetVtable() const {
- return reinterpret_cast<ManagedVTable *>(mm_data & PointerMask);
- }
- inline bool isMarked() const {
- return mm_data & MarkBit;
- }
- inline void setMarkBit() {
- mm_data |= MarkBit;
- }
- inline void clearMarkBit() {
- mm_data &= ~MarkBit;
- }
-
- inline bool inUse() const {
- return !(mm_data & NotInUse);
- }
-
- Base *nextFree() {
- return reinterpret_cast<Base *>(mm_data & PointerMask);
- }
- void setNextFree(Base *m) {
- mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
- }
-
- void *operator new(size_t, Managed *m) { return m; }
- void *operator new(size_t, Heap::Base *m) { return m; }
- void operator delete(void *, Heap::Base *) {}
-};
-
+ struct Base;
}
+typedef uint Bool;
+
struct Q_QML_PRIVATE_EXPORT Value
{
/*
@@ -326,13 +283,11 @@ struct Q_QML_PRIVATE_EXPORT Value
return v;
}
- static inline Value fromManaged(Managed *m);
-
int toUInt16() const;
inline int toInt32() const;
inline unsigned int toUInt32() const;
- inline bool toBoolean() const;
+ bool toBoolean() const;
double toInteger() const;
inline double toNumber() const;
double toNumberImpl() const;
@@ -349,17 +304,28 @@ struct Q_QML_PRIVATE_EXPORT Value
return b;
}
- inline String *asString() const;
- inline Managed *asManaged() const;
- inline Object *asObject() const;
- inline FunctionObject *asFunctionObject() const;
- inline NumberObject *asNumberObject() const;
- inline StringObject *asStringObject() const;
- inline DateObject *asDateObject() const;
- inline ArrayObject *asArrayObject() const;
- inline ErrorObject *asErrorObject() const;
+ template <typename T>
+ const T *as() const {
+ if (!m || !isManaged())
+ return 0;
+
+ Q_ASSERT(m->vtable);
+#if !defined(QT_NO_QOBJECT_CHECK)
+ static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this));
+#endif
+ const VTable *vt = m->vtable;
+ while (vt) {
+ if (vt == T::staticVTable())
+ return static_cast<const T *>(this);
+ vt = vt->parent;
+ }
+ return 0;
+ }
+ template <typename T>
+ T *as() {
+ return const_cast<T *>(const_cast<const Value *>(this)->as<T>());
+ }
- template<typename T> inline T *as() const;
template<typename T> inline T *cast() {
return static_cast<T *>(managed());
}
@@ -368,7 +334,9 @@ struct Q_QML_PRIVATE_EXPORT Value
}
inline uint asArrayIndex() const;
- inline uint asArrayLength(bool *ok) const;
+#ifndef V4_BOOTSTRAP
+ uint asArrayLength(bool *ok) const;
+#endif
ReturnedValue asReturnedValue() const { return val; }
static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
@@ -376,12 +344,17 @@ struct Q_QML_PRIVATE_EXPORT Value
// Section 9.12
bool sameValue(Value other) const;
- inline void mark(ExecutionEngine *e) const;
+ inline void mark(ExecutionEngine *e);
Value &operator =(const ScopedValue &v);
Value &operator=(ReturnedValue v) { val = v; return *this; }
Value &operator=(Managed *m) {
- val = Value::fromManaged(m).val;
+ if (!m) {
+ tag = Undefined_Type;
+ uint_32 = 0;
+ } else {
+ val = reinterpret_cast<Value *>(m)->val;
+ }
return *this;
}
Value &operator=(Heap::Base *o) {
@@ -400,13 +373,64 @@ struct Q_QML_PRIVATE_EXPORT Value
}
};
-inline Managed *Value::asManaged() const
+inline bool Value::isString() const
+{
+ if (!isManaged())
+ return false;
+ return m && m->vtable->isString;
+}
+inline bool Value::isObject() const
+{
+ if (!isManaged())
+ return false;
+ return m && m->vtable->isObject;
+}
+
+inline bool Value::isPrimitive() const
+{
+ return !isObject();
+}
+
+inline double Value::toNumber() const
+{
+ if (isInteger())
+ return int_32;
+ if (isDouble())
+ return doubleValue();
+ return toNumberImpl();
+}
+
+
+#ifndef V4_BOOTSTRAP
+inline uint Value::asArrayIndex() const
+{
+#if QT_POINTER_SIZE == 8
+ if (!isNumber())
+ return UINT_MAX;
+ if (isInteger())
+ return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
+#else
+ if (isInteger() && int_32 >= 0)
+ return (uint)int_32;
+ if (!isDouble())
+ return UINT_MAX;
+#endif
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d)
+ return UINT_MAX;
+ return idx;
+}
+#endif
+
+inline
+ReturnedValue Heap::Base::asReturnedValue() const
{
- if (isManaged())
- return managed();
- return 0;
+ return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
}
+
+
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
inline static Primitive emptyValue();
@@ -445,34 +469,52 @@ inline Primitive Primitive::emptyValue()
return v;
}
-template <typename T>
-struct TypedValue : public Value
+inline Primitive Primitive::nullValue()
{
- template<typename X>
- TypedValue &operator =(X *x) {
- m = x;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
+ Primitive v;
+#if QT_POINTER_SIZE == 8
+ v.val = quint64(_Null_Type) << Tag_Shift;
+#else
+ v.tag = _Null_Type;
+ v.int_32 = 0;
#endif
- return *this;
- }
- TypedValue &operator =(T *t);
- TypedValue &operator =(const Scoped<T> &v);
-// TypedValue &operator =(const ManagedRef<T> &v);
-
- TypedValue &operator =(const TypedValue<T> &t);
+ return v;
+}
- bool operator!() const { return !managed(); }
+inline Primitive Primitive::fromBoolean(bool b)
+{
+ Primitive v;
+ v.tag = _Boolean_Type;
+ v.int_32 = (bool)b;
+ return v;
+}
- operator T *() { return static_cast<T *>(managed()); }
- T *operator->() { return static_cast<T *>(managed()); }
- const T *operator->() const { return static_cast<T *>(managed()); }
- T *getPointer() const { return static_cast<T *>(managed()); }
+inline Primitive Primitive::fromDouble(double d)
+{
+ Primitive v;
+ v.setDouble(d);
+ return v;
+}
- void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
-};
-typedef TypedValue<String> StringValue;
+inline Primitive Primitive::fromInt32(int i)
+{
+ Primitive v;
+ v.tag = _Integer_Type;
+ v.int_32 = i;
+ return v;
+}
+inline Primitive Primitive::fromUInt32(uint i)
+{
+ Primitive v;
+ if (i < INT_MAX) {
+ v.tag = _Integer_Type;
+ v.int_32 = (int)i;
+ } else {
+ v.setDouble(i);
+ }
+ return v;
+}
struct Encode {
static ReturnedValue undefined() {
@@ -519,21 +561,29 @@ private:
Encode(void *);
};
-inline
-ReturnedValue Heap::Base::asReturnedValue() const
+template<typename T>
+ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
+
+inline int Value::toInt32() const
{
- return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
-}
+ if (isInteger())
+ return int_32;
+ double d = isNumber() ? doubleValue() : toNumberImpl();
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
-template<typename T>
-T *value_cast(const Value &v)
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Primitive::toInt32(d);
+}
+
+inline unsigned int Value::toUInt32() const
{
- return v.as<T>();
+ return (unsigned int)toInt32();
}
-template<typename T>
-ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
}
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 966f83acef..c919d24461 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -44,7 +44,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value)
- : Heap::Object(engine->emptyClass, engine->variantPrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->variantPrototype())
{
data = value;
if (isScarce())
@@ -96,8 +96,8 @@ void VariantPrototype::init()
{
defineDefaultProperty(QStringLiteral("preserve"), method_preserve, 0);
defineDefaultProperty(QStringLiteral("destroy"), method_destroy, 0);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
- defineDefaultProperty(engine()->id_toString, method_toString, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
+ defineDefaultProperty(engine()->id_toString(), method_toString, 0);
}
QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx)
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 2b48412c4d..b19f12bb98 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -49,7 +49,7 @@
#include <QtQml/qqmllist.h>
#include <QtCore/qvariant.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index dda5848f0b..761e377f75 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -37,13 +37,14 @@
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv4function_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4math_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4lookup_p.h>
+#include <private/qv4string_p.h>
#include <iostream>
#include "qv4alloca_p.h"
@@ -858,7 +859,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
engine->currentContext()->lineNumber = instr.lineNumber;
if (qt_v4IsDebugging)
qt_v4CheckForBreak(context, scopes, scopeDepth);
- MOTH_END_INSTR(Debug)
+ MOTH_END_INSTR(Line)
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->thisObject();
diff --git a/src/qml/memory/memory.pri b/src/qml/memory/memory.pri
new file mode 100644
index 0000000000..04b7566ccc
--- /dev/null
+++ b/src/qml/memory/memory.pri
@@ -0,0 +1,14 @@
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$OUT_PWD
+
+!qmldevtools_build {
+SOURCES += \
+ $$PWD/qv4mm.cpp \
+
+HEADERS += \
+ $$PWD/qv4mm_p.h
+
+}
+
+HEADERS += \
+ $$PWD/qv4heap_p.h
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
new file mode 100644
index 0000000000..606fd47cbb
--- /dev/null
+++ b/src/qml/memory/qv4heap_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4HEAP_P_H
+#define QV4HEAP_P_H
+
+#include <QtCore/QString>
+#include <private/qv4global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct VTable
+{
+ const VTable * const parent;
+ uint isExecutionContext : 1;
+ uint isString : 1;
+ uint isObject : 1;
+ uint isFunctionObject : 1;
+ uint isErrorObject : 1;
+ uint isArrayData : 1;
+ uint unused : 18;
+ uint type : 8;
+ const char *className;
+ void (*destroy)(Heap::Base *);
+ void (*markObjects)(Heap::Base *, ExecutionEngine *e);
+ bool (*isEqualTo)(Managed *m, Managed *other);
+};
+
+namespace Heap {
+
+struct Q_QML_EXPORT Base {
+ union {
+ const VTable *vtable;
+ quintptr mm_data;
+ };
+
+ inline ReturnedValue asReturnedValue() const;
+ inline void mark(QV4::ExecutionEngine *engine);
+
+ enum {
+ MarkBit = 0x1,
+ NotInUse = 0x2,
+ PointerMask = ~0x3
+ };
+
+ VTable *gcGetVtable() const {
+ return reinterpret_cast<VTable *>(mm_data & PointerMask);
+ }
+ inline bool isMarked() const {
+ return mm_data & MarkBit;
+ }
+ inline void setMarkBit() {
+ mm_data |= MarkBit;
+ }
+ inline void clearMarkBit() {
+ mm_data &= ~MarkBit;
+ }
+
+ inline bool inUse() const {
+ return !(mm_data & NotInUse);
+ }
+
+ Base *nextFree() {
+ return reinterpret_cast<Base *>(mm_data & PointerMask);
+ }
+ void setNextFree(Base *m) {
+ mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
+ }
+
+ void *operator new(size_t, Managed *m) { return m; }
+ void *operator new(size_t, Heap::Base *m) { return m; }
+ void operator delete(void *, Heap::Base *) {}
+};
+
+template <typename T>
+struct Pointer {
+ Pointer() {}
+ Pointer(T *t) : ptr(t) {}
+
+ T *operator->() const { return ptr; }
+ operator T *() const { return ptr; }
+
+ Pointer &operator =(T *t) { ptr = t; return *this; }
+
+ template <typename Type>
+ Type *cast() { return static_cast<Type *>(ptr); }
+
+ T *ptr;
+};
+
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index d5576b400a..7dbf12ff11 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -381,7 +381,7 @@ void MemoryManager::sweep(bool lastSweep)
{
if (m_weakValues) {
for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
- if (Managed *m = (*it).asManaged()) {
+ if (Managed *m = (*it).as<Managed>()) {
if (!m->markBit())
(*it) = Primitive::undefinedValue();
}
@@ -525,7 +525,7 @@ void MemoryManager::runGC()
size_t MemoryManager::getUsedMem() const
{
size_t usedMem = 0;
- for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
+ for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
@@ -607,7 +607,7 @@ void MemoryManager::collectFromJSStack() const
Value *v = m_d->engine->jsStackBase;
Value *top = m_d->engine->jsStackTop;
while (v < top) {
- Managed *m = v->asManaged();
+ Managed *m = v->as<Managed>();
if (m && m->inUse())
// Skip pointers to already freed objects, they are bogus as well
m->mark(m_d->engine);
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 00b41b796a..422809ba54 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -34,9 +34,9 @@
#ifndef QV4GC_H
#define QV4GC_H
-#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
+#include <private/qv4global_p.h>
+#include <private/qv4value_p.h>
+#include <private/qv4scopedvalue_p.h>
//#define DETAILED_MM_STATS
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 6e06fb42ef..d75262bf0b 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -8,6 +8,9 @@ win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
win32:!wince*:!winrt:LIBS += -lshell32
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+# Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT.
+gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
+
MODULE_PLUGIN_TYPES = \
qmltooling
@@ -33,6 +36,7 @@ HEADERS += qtqmlglobal.h \
#modules
include(util/util.pri)
+include(memory/memory.pri)
include(parser/parser.pri)
include(compiler/compiler.pri)
include(jsapi/jsapi.pri)
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index 59ed77b580..ba2ca43990 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -72,13 +72,16 @@ template<class T>
class QQmlRefPointer
{
public:
+ enum Mode {
+ AddRef,
+ Adopt
+ };
inline QQmlRefPointer();
- inline QQmlRefPointer(T *);
+ inline QQmlRefPointer(T *, Mode m = AddRef);
inline QQmlRefPointer(const QQmlRefPointer<T> &);
inline ~QQmlRefPointer();
inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
- inline QQmlRefPointer<T> &operator=(T *);
inline bool isNull() const { return !o; }
@@ -87,7 +90,7 @@ public:
inline operator T*() const { return o; }
inline T* data() const { return o; }
- inline QQmlRefPointer<T> &take(T *);
+ inline QQmlRefPointer<T> &adopt(T *);
private:
T *o;
@@ -133,10 +136,11 @@ QQmlRefPointer<T>::QQmlRefPointer()
}
template<class T>
-QQmlRefPointer<T>::QQmlRefPointer(T *o)
+QQmlRefPointer<T>::QQmlRefPointer(T *o, Mode m)
: o(o)
{
- if (o) o->addref();
+ if (m == AddRef && o)
+ o->addref();
}
template<class T>
@@ -161,21 +165,12 @@ QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other)
return *this;
}
-template<class T>
-QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(T *other)
-{
- if (other) other->addref();
- if (o) o->release();
- o = other;
- return *this;
-}
-
/*!
Takes ownership of \a other. take() does *not* add a reference, as it assumes ownership
of the callers reference of other.
*/
template<class T>
-QQmlRefPointer<T> &QQmlRefPointer<T>::take(T *other)
+QQmlRefPointer<T> &QQmlRefPointer<T>::adopt(T *other)
{
if (o) o->release();
o = other;
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 4addcd9e58..62f6f76a7e 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -377,4 +377,31 @@ void QQmlThread::internalPostMethodToMain(Message *message)
d->unlock();
}
+void QQmlThread::waitForNextMessage()
+{
+ Q_ASSERT(!isThisThread());
+ d->lock();
+ Q_ASSERT(d->m_mainThreadWaiting == false);
+
+ d->m_mainThreadWaiting = true;
+
+ if (d->mainSync || !d->threadList.isEmpty()) {
+ if (d->mainSync) {
+ QQmlThread::Message *message = d->mainSync;
+ unlock();
+ message->call(this);
+ delete message;
+ lock();
+ d->mainSync = 0;
+ wakeOne();
+ } else {
+ d->wait();
+ }
+ }
+
+ d->m_mainThreadWaiting = false;
+ d->unlock();
+}
+
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h
index 86d7d2cf19..73658536ac 100644
--- a/src/qml/qml/ftw/qqmlthread_p.h
+++ b/src/qml/qml/ftw/qqmlthread_p.h
@@ -108,6 +108,8 @@ public:
template<typename T, typename T2, class V, class V2, class O>
inline void postMethodToMain(void (O::*Member)(V, V2), const T &, const T2 &);
+ void waitForNextMessage();
+
protected:
virtual void startupThread();
virtual void shutdownThread();
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index e733bcec05..10ae9f0e52 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -35,7 +35,6 @@ SOURCES += \
$$PWD/qqmlimport.cpp \
$$PWD/qqmllist.cpp \
$$PWD/qqmllocale.cpp \
- $$PWD/qqmlabstractexpression.cpp \
$$PWD/qqmljavascriptexpression.cpp \
$$PWD/qqmlabstractbinding.cpp \
$$PWD/qqmlvaluetypeproxybinding.cpp \
@@ -107,7 +106,6 @@ HEADERS += \
$$PWD/qqmlscriptstring_p.h \
$$PWD/qqmllocale_p.h \
$$PWD/qqmlcomponentattached_p.h \
- $$PWD/qqmlabstractexpression_p.h \
$$PWD/qqmljavascriptexpression_p.h \
$$PWD/qqmlabstractbinding_p.h \
$$PWD/qqmlvaluetypeproxybinding_p.h \
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp
index 40c8f451b4..4e0763e95a 100644
--- a/src/qml/qml/qqmlabstractbinding.cpp
+++ b/src/qml/qml/qqmlabstractbinding.cpp
@@ -39,24 +39,19 @@
QT_BEGIN_NAMESPACE
-extern QQmlAbstractBinding::VTable QQmlBinding_vtable;
-extern QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable;
-
-QQmlAbstractBinding::VTable *QQmlAbstractBinding::vTables[] = {
- &QQmlBinding_vtable,
- &QQmlValueTypeProxyBinding_vtable
-};
-
-QQmlAbstractBinding::QQmlAbstractBinding(BindingType bt)
- : m_nextBindingPtr(bt)
+QQmlAbstractBinding::QQmlAbstractBinding()
+ : m_targetIndex(-1)
{
+ Q_ASSERT(!isAddedToObject());
}
QQmlAbstractBinding::~QQmlAbstractBinding()
{
- Q_ASSERT(isAddedToObject() == false);
- Q_ASSERT(nextBinding() == 0);
- Q_ASSERT(*m_mePtr == 0);
+ Q_ASSERT(!ref);
+ Q_ASSERT(!isAddedToObject());
+
+ if (m_nextBinding.data() && !m_nextBinding->ref.deref())
+ delete m_nextBinding.data();
}
/*!
@@ -72,40 +67,45 @@ void QQmlAbstractBinding::addToObject()
Q_ASSERT(!nextBinding());
Q_ASSERT(isAddedToObject() == false);
- QObject *obj = object();
+ QObject *obj = targetObject();
Q_ASSERT(obj);
QQmlData *data = QQmlData::get(obj, true);
int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
// Value type
// Find the value type proxy (if there is one)
QQmlValueTypeProxyBinding *proxy = 0;
if (data->hasBindingBit(coreIndex)) {
QQmlAbstractBinding *b = data->bindings;
- while (b && b->propertyIndex() != coreIndex)
+ while (b && b->targetPropertyIndex() != coreIndex)
b = b->nextBinding();
- Q_ASSERT(b && b->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
+ Q_ASSERT(b && b->isValueTypeProxy());
proxy = static_cast<QQmlValueTypeProxyBinding *>(b);
}
if (!proxy) {
proxy = new QQmlValueTypeProxyBinding(obj, coreIndex);
- Q_ASSERT(proxy->propertyIndex() == coreIndex);
- Q_ASSERT(proxy->object() == obj);
+ Q_ASSERT(proxy->targetPropertyIndex() == coreIndex);
+ Q_ASSERT(proxy->targetObject() == obj);
proxy->addToObject();
}
- setNextBinding(proxy->m_bindings);
+ setNextBinding(proxy->m_bindings.data());
proxy->m_bindings = this;
} else {
setNextBinding(data->bindings);
+ if (data->bindings) {
+ data->bindings->ref.deref();
+ Q_ASSERT(data->bindings->ref.refCount > 0);
+ }
data->bindings = this;
+ ref.ref();
data->setBindingBit(obj, coreIndex);
}
@@ -118,95 +118,81 @@ Remove the binding from the object.
*/
void QQmlAbstractBinding::removeFromObject()
{
- if (isAddedToObject()) {
- QObject *obj = object();
- QQmlData *data = QQmlData::get(obj, false);
- Q_ASSERT(data);
-
- int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
-
- // Find the value type binding
- QQmlAbstractBinding *vtbinding = data->bindings;
- while (vtbinding->propertyIndex() != coreIndex) {
- vtbinding = vtbinding->nextBinding();
- Q_ASSERT(vtbinding);
- }
- Q_ASSERT(vtbinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
-
- QQmlValueTypeProxyBinding *vtproxybinding =
- static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
-
- QQmlAbstractBinding *binding = vtproxybinding->m_bindings;
- if (binding == this) {
- vtproxybinding->m_bindings = nextBinding();
- } else {
- while (binding->nextBinding() != this) {
- binding = binding->nextBinding();
- Q_ASSERT(binding);
- }
- binding->setNextBinding(nextBinding());
- }
-
- // Value type - we don't remove the proxy from the object. It will sit their happily
- // doing nothing until it is removed by a write, a binding change or it is reused
- // to hold more sub-bindings.
+ if (!isAddedToObject())
+ return;
- } else {
+ setAddedToObject(false);
- if (data->bindings == this) {
- data->bindings = nextBinding();
- } else {
- QQmlAbstractBinding *binding = data->bindings;
- while (binding->nextBinding() != this) {
- binding = binding->nextBinding();
- Q_ASSERT(binding);
- }
- binding->setNextBinding(nextBinding());
- }
-
- data->clearBindingBit(coreIndex);
- }
+ QObject *obj = targetObject();
+ QQmlData *data = QQmlData::get(obj, false);
+ Q_ASSERT(data);
- setNextBinding(0);
- setAddedToObject(false);
- }
-}
+ QQmlAbstractBinding::Ptr next;
+ next = nextBinding();
+ setNextBinding(0);
-void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
-{
- qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
-}
+ int coreIndex;
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
+ // Find the value type binding
+ QQmlAbstractBinding *vtbinding = data->bindings;
+ while (vtbinding->targetPropertyIndex() != coreIndex) {
+ vtbinding = vtbinding->nextBinding();
+ Q_ASSERT(vtbinding);
+ }
+ Q_ASSERT(vtbinding->isValueTypeProxy());
-static void bindingDummyDeleter(QQmlAbstractBinding *)
-{
-}
+ QQmlValueTypeProxyBinding *vtproxybinding =
+ static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
-QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer()
-{
- if (m_mePtr.value().isNull())
- m_mePtr.value() = QSharedPointer<QQmlAbstractBinding>(this, bindingDummyDeleter);
+ QQmlAbstractBinding *binding = vtproxybinding->m_bindings.data();
+ if (binding == this) {
+ vtproxybinding->m_bindings = next;
+ } else {
+ while (binding->nextBinding() != this) {
+ binding = binding->nextBinding();
+ Q_ASSERT(binding);
+ }
+ binding->setNextBinding(next.data());
+ }
- return m_mePtr.value().toWeakRef();
-}
+ // Value type - we don't remove the proxy from the object. It will sit their happily
+ // doing nothing until it is removed by a write, a binding change or it is reused
+ // to hold more sub-bindings.
+ return;
+ }
-void QQmlAbstractBinding::clear()
-{
- if (!m_mePtr.isNull()) {
- **m_mePtr = 0;
- m_mePtr = 0;
+ if (data->bindings == this) {
+ if (next.data())
+ next->ref.ref();
+ data->bindings = next.data();
+ if (!ref.deref())
+ delete this;
+ } else {
+ QQmlAbstractBinding *binding = data->bindings;
+ while (binding->nextBinding() != this) {
+ binding = binding->nextBinding();
+ Q_ASSERT(binding);
+ }
+ binding->setNextBinding(next.data());
}
+
+ data->clearBindingBit(coreIndex);
}
-void QQmlAbstractBinding::default_retargetBinding(QQmlAbstractBinding *, QObject *, int)
+void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
{
- qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding.");
+ qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
}
-QString QQmlAbstractBinding::default_expression(const QQmlAbstractBinding *)
+QString QQmlAbstractBinding::expression() const
{
return QLatin1String("<Unknown>");
}
+bool QQmlAbstractBinding::isValueTypeProxy() const
+{
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index b5d8181ca5..dd14301aa9 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -46,6 +46,7 @@
//
#include <QtCore/qsharedpointer.h>
+#include <QtCore/qshareddata.h>
#include <private/qtqmlglobal_p.h>
#include <private/qqmlproperty_p.h>
#include <private/qpointervaluepair_p.h>
@@ -56,162 +57,83 @@ class QQmlObjectCreator;
class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding
{
+protected:
+ QQmlAbstractBinding();
public:
- enum DestroyMode {
-
- // The binding should disconnect itself upon destroy
- DisconnectBinding,
-
- // The binding doesn't need to disconnect itself, but it can if it wants to.
- //
- // This is used in QQmlData::destroyed() - at the point at which the bindings are
- // destroyed, the notifiers are already disconnected, so no need to disconnect each
- // binding again.
- //
- // Bindings can use this flag to speed up destruction, especially for v4 bindings
- // disconnecting a single binding might be slow.
- KeepBindingConnected
- };
-
- struct VTable {
- void (*destroy)(QQmlAbstractBinding *, DestroyMode destroyMode);
- QString (*expression)(const QQmlAbstractBinding *);
- int (*propertyIndex)(const QQmlAbstractBinding *);
- QObject *(*object)(const QQmlAbstractBinding *);
- void (*setEnabled)(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- void (*update)(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- void (*retargetBinding)(QQmlAbstractBinding *, QObject *, int);
- };
-
- typedef QWeakPointer<QQmlAbstractBinding> Pointer;
+ virtual ~QQmlAbstractBinding();
- enum BindingType { Binding = 0, ValueTypeProxy = 1 };
- inline BindingType bindingType() const;
+ typedef QExplicitlySharedDataPointer<QQmlAbstractBinding> Ptr;
- // Destroy the binding. Use this instead of calling delete.
- // Bindings are free to implement their own memory management, so the delete operator is
- // not necessarily safe. The default implementation clears the binding, removes it from
- // the object and calls delete.
- void destroy(DestroyMode destroyMode = DisconnectBinding)
- { vtable()->destroy(this, destroyMode); }
+ virtual QString expression() const;
- QString expression() const { return vtable()->expression(this); }
+ virtual bool isValueTypeProxy() const;
// Should return the encoded property index for the binding. Should return this value
// even if the binding is not enabled or added to an object.
// Encoding is: coreIndex | (valueTypeIndex << 16)
- int propertyIndex() const { return vtable()->propertyIndex(this); }
+ int targetPropertyIndex() const { return m_targetIndex; }
// Should return the object for the binding. Should return this object even if the
// binding is not enabled or added to the object.
- QObject *object() const { return vtable()->object(this); }
-
- void setEnabled(bool e) { setEnabled(e, QQmlPropertyPrivate::DontRemoveBinding); }
- void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f) { vtable()->setEnabled(this, e, f); }
+ QObject *targetObject() const { return m_target.data(); }
- void update() { update(QQmlPropertyPrivate::DontRemoveBinding); }
- void update(QQmlPropertyPrivate::WriteFlags f) { vtable()->update(this, f); }
+ virtual void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f = QQmlPropertyPrivate::DontRemoveBinding) = 0;
void addToObject();
void removeFromObject();
- static inline Pointer getPointer(QQmlAbstractBinding *p);
static void printBindingLoopError(QQmlProperty &prop);
- // Default implementation for some VTable functions
- template<typename T>
- static void default_destroy(QQmlAbstractBinding *, DestroyMode);
- static QString default_expression(const QQmlAbstractBinding *);
- static void default_retargetBinding(QQmlAbstractBinding *, QObject *, int);
-
-protected:
- QQmlAbstractBinding(BindingType);
- ~QQmlAbstractBinding();
- void clear();
+ inline QQmlAbstractBinding *nextBinding() const;
- // Called by QQmlPropertyPrivate to "move" a binding to a different property.
- // This is only used for alias properties. The default implementation qFatal()'s
- // to ensure that the method is never called for binding types that don't support it.
- void retargetBinding(QObject *o, int i) { vtable()->retargetBinding(this, o, i); }
-private:
- Pointer weakPointer();
+ struct RefCount {
+ RefCount() : refCount(0) {}
+ int refCount;
+ void ref() { ++refCount; }
+ int deref() { return --refCount; }
+ operator int() const { return refCount; }
+ };
+ RefCount ref;
+protected:
friend class QQmlData;
- friend class QQmlComponentPrivate;
friend class QQmlValueTypeProxyBinding;
- friend class QQmlPropertyPrivate;
- friend class QtSharedPointer::ExternalRefCount<QQmlAbstractBinding>;
- friend class QV4Bindings;
friend class QQmlObjectCreator;
- typedef QSharedPointer<QQmlAbstractBinding> SharedPointer;
- // To save memory, we also store the rarely used weakPointer() instance in here
- // We also use the flag bits:
- // m_mePtr.flag1: added to object
- QPointerValuePair<QQmlAbstractBinding*, SharedPointer> m_mePtr;
-
inline void setAddedToObject(bool v);
inline bool isAddedToObject() const;
- inline QQmlAbstractBinding *nextBinding() const;
inline void setNextBinding(QQmlAbstractBinding *);
+ int m_targetIndex;
+ QFlagPointer<QObject> m_target;
// Pointer to the next binding in the linked list of bindings.
- // Being a pointer, the address is always aligned to at least 4 bytes, which means the last two
- // bits of the pointer are free to be used for something else. They are used to store the binding
- // type. The binding type serves as an index into the static vTables array, which is used instead
- // of a compiler-generated vTable. Instead of virtual functions, pointers to static functions in
- // the vTables array are used for dispatching.
- // This saves a compiler-generated pointer to a compiler-generated vTable, and thus reduces
- // the binding object size by sizeof(void*).
- qintptr m_nextBindingPtr;
-
- static VTable *vTables[];
- inline const VTable *vtable() const { return vTables[bindingType()]; }
+ QFlagPointer<QQmlAbstractBinding> m_nextBinding;
};
-QQmlAbstractBinding::Pointer
-QQmlAbstractBinding::getPointer(QQmlAbstractBinding *p)
-{
- return p ? p->weakPointer() : Pointer();
-}
-
void QQmlAbstractBinding::setAddedToObject(bool v)
{
- m_mePtr.setFlagValue(v);
+ m_nextBinding.setFlagValue(v);
}
bool QQmlAbstractBinding::isAddedToObject() const
{
- return m_mePtr.flag();
+ return m_nextBinding.flag();
}
QQmlAbstractBinding *QQmlAbstractBinding::nextBinding() const
{
- return (QQmlAbstractBinding *)(m_nextBindingPtr & ~0x3);
+ return m_nextBinding.data();
}
void QQmlAbstractBinding::setNextBinding(QQmlAbstractBinding *b)
{
- m_nextBindingPtr = qintptr(b) | (m_nextBindingPtr & 0x3);
-}
-
-QQmlAbstractBinding::BindingType QQmlAbstractBinding::bindingType() const
-{
- return (BindingType)(m_nextBindingPtr & 0x3);
-}
-
-template<typename T>
-void QQmlAbstractBinding::default_destroy(QQmlAbstractBinding *This, DestroyMode mode)
-{
- // Assume the binding disconnects itself in the destructor, which for example QQmlBinding
- // does in the destructor of its base class, QQmlJavaScriptExpression
- Q_UNUSED(mode);
-
- This->removeFromObject();
- This->clear();
- delete static_cast<T *>(This);
+ if (b)
+ b->ref.ref();
+ if (m_nextBinding.data() && !m_nextBinding->ref.deref())
+ delete m_nextBinding.data();
+ m_nextBinding = b;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlabstractexpression_p.h b/src/qml/qml/qqmlabstractexpression_p.h
deleted file mode 100644
index 82ba010434..0000000000
--- a/src/qml/qml/qqmlabstractexpression_p.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLABSTRACTEXPRESSION_P_H
-#define QQMLABSTRACTEXPRESSION_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 <private/qqmlcontext_p.h>
-#include <private/qfieldlist_p.h>
-#include <private/qflagpointer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlAbstractExpression
-{
-public:
- QQmlAbstractExpression();
- virtual ~QQmlAbstractExpression();
-
- bool isValid() const;
-
- QQmlContextData *context() const;
- void setContext(QQmlContextData *);
-
- virtual void refresh();
-
- class DeleteWatcher {
- public:
- inline DeleteWatcher(QQmlAbstractExpression *);
- inline ~DeleteWatcher();
- inline bool wasDeleted() const;
- private:
- friend class QQmlAbstractExpression;
- QQmlContextData *_c;
- QQmlAbstractExpression **_w;
- QQmlAbstractExpression *_s;
- };
-
-private:
- friend class QQmlContext;
- friend class QQmlContextData;
- friend class QQmlContextPrivate;
-
- QBiPointer<QQmlContextData, DeleteWatcher> m_context;
- QQmlAbstractExpression **m_prevExpression;
- QQmlAbstractExpression *m_nextExpression;
-};
-
-QQmlAbstractExpression::DeleteWatcher::DeleteWatcher(QQmlAbstractExpression *e)
-: _c(0), _w(0), _s(e)
-{
- if (e->m_context.isT1()) {
- _w = &_s;
- _c = e->m_context.asT1();
- e->m_context = this;
- } else {
- // Another watcher is already registered
- _w = &e->m_context.asT2()->_s;
- }
-}
-
-QQmlAbstractExpression::DeleteWatcher::~DeleteWatcher()
-{
- Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_context.isT2()));
- if (*_w && _s->m_context.asT2() == this)
- _s->m_context = _c;
-}
-
-bool QQmlAbstractExpression::DeleteWatcher::wasDeleted() const
-{
- return *_w == 0;
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLABSTRACTEXPRESSION_P_H
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index f223d099e4..b0ccf9ac59 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -43,43 +43,27 @@
#include <private/qqmlscriptstring_p.h>
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
+#include <private/qqmlvmemetaobject_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
-// Used in qqmlabstractbinding.cpp
-QQmlAbstractBinding::VTable QQmlBinding_vtable = {
- QQmlAbstractBinding::default_destroy<QQmlBinding>,
- QQmlBinding::expression,
- QQmlBinding::propertyIndex,
- QQmlBinding::object,
- QQmlBinding::setEnabled,
- QQmlBinding::update,
- QQmlBinding::retargetBinding
-};
-
-QQmlBinding::Identifier QQmlBinding::Invalid = -1;
-
-static QQmlJavaScriptExpression::VTable QQmlBinding_jsvtable = {
- QQmlBinding::expressionIdentifier,
- QQmlBinding::expressionChanged
-};
-
QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt));
+ QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt));
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(context(), obj, str, QString(), 0));
+ createQmlBinding(context(), obj, str, QString(), 0);
}
QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
if (ctxt && !ctxt->isValid())
return;
@@ -100,51 +84,52 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
}
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
+ QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
setScopeObject(obj ? obj : scriptPrivate->scope);
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
if (runtimeFunction) {
- v4function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction));
+ m_function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction));
} else {
QString code = scriptPrivate->script;
- v4function.set(v4, qmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber));
+ createQmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber);
}
}
QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(ctxt, obj, str, QString(), 0));
+ createQmlBinding(ctxt, obj, str, QString(), 0);
}
QQmlBinding::QQmlBinding(const QString &str, QObject *obj,
QQmlContextData *ctxt,
const QString &url, quint16 lineNumber, quint16 columnNumber)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
Q_UNUSED(columnNumber);
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(ctxt, obj, str, url, lineNumber));
+ createQmlBinding(ctxt, obj, str, url, lineNumber);
}
QQmlBinding::QQmlBinding(const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- v4function.set(functionPtr.asObject()->engine(), functionPtr);
+ m_function.set(functionPtr.as<QV4::Object>()->engine(), functionPtr);
}
QQmlBinding::~QQmlBinding()
@@ -162,90 +147,238 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
return;
// Check that the target has not been deleted
- if (QQmlData::wasDeleted(object()))
+ if (QQmlData::wasDeleted(targetObject()))
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
- QV4::ScopedFunctionObject f(scope, v4function.value());
+ QV4::ScopedFunctionObject f(scope, m_function.value());
Q_ASSERT(f);
- if (!updatingFlag()) {
- QQmlBindingProfiler prof(ep->profiler, f);
- setUpdatingFlag(true);
+ if (updatingFlag()) {
+ QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), getPropertyData(), 0);
+ QQmlAbstractBinding::printBindingLoopError(p);
+ return;
+ }
+
+ QQmlBindingProfiler prof(ep->profiler, f);
+ setUpdatingFlag(true);
- QQmlAbstractExpression::DeleteWatcher watcher(this);
+ QQmlJavaScriptExpression::DeleteWatcher watcher(this);
- if (m_core.propType == qMetaTypeId<QQmlBinding *>()) {
+ QQmlPropertyData pd = getPropertyData();
- int idx = m_core.coreIndex;
- Q_ASSERT(idx != -1);
+ if (pd.propType == qMetaTypeId<QQmlBinding *>()) {
- QQmlBinding *t = this;
- int status = -1;
- void *a[] = { &t, 0, &status, &flags };
- QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a);
+ int idx = pd.coreIndex;
+ Q_ASSERT(idx != -1);
- } else {
- ep->referenceScarceResources();
+ QQmlBinding *t = this;
+ int status = -1;
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(*m_target, QMetaObject::WriteProperty, idx, a);
- bool isUndefined = false;
+ } else {
+ ep->referenceScarceResources();
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined));
+ bool isUndefined = false;
- bool needsErrorLocationData = false;
- if (!watcher.wasDeleted() && !hasError())
- needsErrorLocationData = !QQmlPropertyPrivate::writeBinding(*m_coreObject, m_core, context(),
- this, result, isUndefined, flags);
+ QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
- if (!watcher.wasDeleted()) {
+ bool error = false;
+ if (!watcher.wasDeleted() && isAddedToObject() && !hasError())
+ error = !write(pd, result, isUndefined, flags);
- if (needsErrorLocationData)
- delayedError()->setErrorLocation(f->sourceLocation());
+ if (!watcher.wasDeleted()) {
- if (hasError()) {
- if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
- } else {
- clearError();
- }
+ if (error) {
+ delayedError()->setErrorLocation(f->sourceLocation());
+ delayedError()->setErrorObject(m_target.data());
+ }
+ if (hasError()) {
+ if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
+ } else {
+ clearError();
}
- ep->dereferenceScarceResources();
}
- if (!watcher.wasDeleted())
- setUpdatingFlag(false);
- } else {
- QQmlProperty p = property();
- QQmlAbstractBinding::printBindingLoopError(p);
+ ep->dereferenceScarceResources();
}
+
+ if (!watcher.wasDeleted())
+ setUpdatingFlag(false);
+}
+
+// Returns true if successful, false if an error description was set on expression
+bool QQmlBinding::write(const QQmlPropertyData &core,
+ const QV4::Value &result, bool isUndefined,
+ QQmlPropertyPrivate::WriteFlags flags)
+{
+ Q_ASSERT(m_target.data());
+ Q_ASSERT(core.coreIndex != -1);
+
+ QQmlEngine *engine = context()->engine;
+ QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
+
+#define QUICK_STORE(cpptype, conversion) \
+ { \
+ cpptype o = (conversion); \
+ int status = -1; \
+ void *argv[] = { &o, 0, &status, &flags }; \
+ QMetaObject::metacall(m_target.data(), QMetaObject::WriteProperty, core.coreIndex, argv); \
+ return true; \
+ } \
+
+
+ if (!isUndefined && !core.isValueTypeVirtual()) {
+ switch (core.propType) {
+ case QMetaType::Int:
+ if (result.isInteger())
+ QUICK_STORE(int, result.integerValue())
+ else if (result.isNumber())
+ QUICK_STORE(int, result.doubleValue())
+ break;
+ case QMetaType::Double:
+ if (result.isNumber())
+ QUICK_STORE(double, result.asDouble())
+ break;
+ case QMetaType::Float:
+ if (result.isNumber())
+ QUICK_STORE(float, result.asDouble())
+ break;
+ case QMetaType::QString:
+ if (result.isString())
+ QUICK_STORE(QString, result.toQStringNoThrow())
+ break;
+ default:
+ break;
+ }
+ }
+#undef QUICK_STORE
+
+ int type = core.isValueTypeVirtual() ? core.valueTypePropType : core.propType;
+
+ QQmlJavaScriptExpression::DeleteWatcher watcher(this);
+
+ QVariant value;
+ bool isVarProperty = core.isVarProperty();
+
+ if (isUndefined) {
+ } else if (core.isQList()) {
+ value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
+ } else if (result.isNull() && core.isQObject()) {
+ value = QVariant::fromValue((QObject *)0);
+ } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
+ value = QQmlPropertyPrivate::resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context());
+ } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
+ value = QV8Engine::getV4(v8engine)->toVariant(result, type);
+ }
+
+ if (hasError()) {
+ return false;
+ } else if (isVarProperty) {
+ const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
+ if (f && f->isBinding()) {
+ // we explicitly disallow this case to avoid confusion. Users can still store one
+ // in an array in a var property if they need to, but the common case is user error.
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ return false;
+ }
+
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(m_target.data());
+ Q_ASSERT(vmemo);
+ vmemo->setVMEProperty(core.coreIndex, result);
+ } else if (isUndefined && core.isResettable()) {
+ void *args[] = { 0 };
+ QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex, args);
+ } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant(), context(), flags);
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
+ if (f && f->isBinding()) {
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ return false;
+ }
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant::fromValue(
+ QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
+ context(), flags);
+ } else if (isUndefined) {
+ QString errorStr = QLatin1String("Unable to assign [undefined] to ");
+ if (!QMetaType::typeName(type))
+ errorStr += QLatin1String("[unknown property type]");
+ else
+ errorStr += QLatin1String(QMetaType::typeName(type));
+ delayedError()->setErrorDescription(errorStr);
+ return false;
+ } else if (const QV4::FunctionObject *f = result.as<QV4::FunctionObject>()) {
+ if (f->isBinding())
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ else
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
+ return false;
+ } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, value, context(), flags)) {
+
+ if (watcher.wasDeleted())
+ return true;
+
+ const char *valueType = 0;
+ const char *propertyType = 0;
+
+ if (value.userType() == QMetaType::QObjectStar) {
+ if (QObject *o = *(QObject **)value.constData()) {
+ valueType = o->metaObject()->className();
+
+ QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
+ if (!propertyMetaObject.isNull())
+ propertyType = propertyMetaObject.className();
+ }
+ } else if (value.userType() != QVariant::Invalid) {
+ if (value.userType() == QMetaType::VoidStar)
+ valueType = "null";
+ else
+ valueType = QMetaType::typeName(value.userType());
+ }
+
+ if (!valueType)
+ valueType = "undefined";
+ if (!propertyType)
+ propertyType = QMetaType::typeName(type);
+ if (!propertyType)
+ propertyType = "[unknown property type]";
+
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(propertyType));
+ return false;
+ }
+
+ return true;
}
QVariant QQmlBinding::evaluate()
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
- QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources();
bool isUndefined = false;
- QV4::ScopedValue f(scope, v4function.value());
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined));
+ QV4::Scope scope(ep->v4engine());
+ QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
ep->dereferenceScarceResources();
return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
-QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlBinding::expressionIdentifier()
{
- QQmlBinding *This = static_cast<QQmlBinding *>(e);
-
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(This->context()->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
- QV4::ScopedValue f(scope, This->v4function.value());
- QV4::Function *function = f->asFunctionObject()->function();
+ QV4::ScopedValue f(scope, m_function.value());
+ QV4::Function *function = f->as<QV4::FunctionObject>()->function();
QString url = function->sourceFile();
quint16 lineNumber = function->compiledFunction->location.line;
@@ -254,10 +387,9 @@ QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
return url + QLatin1Char(':') + QString::number(lineNumber) + QLatin1Char(':') + QString::number(columnNumber);
}
-void QQmlBinding::expressionChanged(QQmlJavaScriptExpression *e)
+void QQmlBinding::expressionChanged()
{
- QQmlBinding *This = static_cast<QQmlBinding *>(e);
- This->update();
+ update();
}
void QQmlBinding::refresh()
@@ -265,36 +397,6 @@ void QQmlBinding::refresh()
update();
}
-QString QQmlBinding::expression(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->expression();
-}
-
-int QQmlBinding::propertyIndex(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->propertyIndex();
-}
-
-QObject *QQmlBinding::object(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->object();
-}
-
-void QQmlBinding::setEnabled(QQmlAbstractBinding *This, bool e, QQmlPropertyPrivate::WriteFlags f)
-{
- static_cast<QQmlBinding *>(This)->setEnabled(e, f);
-}
-
-void QQmlBinding::update(QQmlAbstractBinding *This , QQmlPropertyPrivate::WriteFlags f)
-{
- static_cast<QQmlBinding *>(This)->update(f);
-}
-
-void QQmlBinding::retargetBinding(QQmlAbstractBinding *This, QObject *o, int i)
-{
- static_cast<QQmlBinding *>(This)->retargetBinding(o, i);
-}
-
void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
{
setEnabledFlag(e);
@@ -307,44 +409,97 @@ void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
QString QQmlBinding::expression() const
{
QV4::Scope scope(QQmlEnginePrivate::get(context()->engine)->v4engine());
- QV4::ScopedValue v(scope, v4function.value());
+ QV4::ScopedValue v(scope, m_function.value());
return v->toQStringNoThrow();
}
-QObject *QQmlBinding::object() const
+void QQmlBinding::setTarget(const QQmlProperty &prop)
{
- if (m_coreObject.hasValue()) return m_coreObject.constValue()->target;
- else return *m_coreObject;
+ setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core);
}
-int QQmlBinding::propertyIndex() const
+void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
{
- if (m_coreObject.hasValue()) return m_coreObject.constValue()->targetProperty;
- else return m_core.encodedIndex();
-}
+ m_target = object;
-void QQmlBinding::retargetBinding(QObject *t, int i)
-{
- m_coreObject.value().target = t;
- m_coreObject.value().targetProperty = i;
-}
+ if (!object) {
+ m_targetIndex = -1;
+ return;
+ }
-void QQmlBinding::setTarget(const QQmlProperty &prop)
-{
- setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core,
- QQmlPropertyPrivate::get(prop)->context);
-}
+ QQmlPropertyData pd = core;
-void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, QQmlContextData *ctxt)
-{
- m_coreObject = object;
- m_core = core;
- m_ctxt = ctxt;
+ if (!object) {
+ m_targetIndex = -1;
+ return;
+ }
+
+ while (pd.isAlias()) {
+ int coreIndex = pd.coreIndex;
+ int valueTypeIndex = pd.getValueTypeCoreIndex();
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+
+ int aValueTypeIndex;
+ if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) {
+ m_target = 0;
+ m_targetIndex = -1;
+ return;
+ }
+ if (valueTypeIndex == -1)
+ valueTypeIndex = aValueTypeIndex;
+
+ QQmlData *data = QQmlData::get(object, false);
+ if (!data || !data->propertyCache) {
+ m_target = 0;
+ m_targetIndex = -1;
+ return;
+ }
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData);
+
+ m_target = object;
+ pd = *propertyData;
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(pd.propType);
+ Q_ASSERT(valueTypeMetaObject);
+ QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
+ pd.setFlags(pd.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
+ pd.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
+ pd.valueTypePropType = vtProp.userType();
+ pd.valueTypeCoreIndex = valueTypeIndex;
+ }
+ }
+ m_targetIndex = pd.encodedIndex();
+
+ QQmlData *data = QQmlData::get(*m_target, true);
+ if (!data->propertyCache) {
+ data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject());
+ data->propertyCache->addref();
+ }
}
-QQmlProperty QQmlBinding::property() const
+QQmlPropertyData QQmlBinding::getPropertyData() const
{
- return QQmlPropertyPrivate::restore(object(), m_core, *m_ctxt);
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(m_targetIndex, &coreIndex);
+
+ QQmlData *data = QQmlData::get(*m_target, false);
+ Q_ASSERT(data && data->propertyCache);
+
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData);
+
+ QQmlPropertyData d = *propertyData;
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d.propType);
+ Q_ASSERT(valueTypeMetaObject);
+ QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
+ d.setFlags(d.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
+ d.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
+ d.valueTypePropType = vtProp.userType();
+ d.valueTypeCoreIndex = valueTypeIndex;
+ }
+ return d;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 1e440b2e86..a435847819 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -57,16 +57,15 @@
#include <private/qpointervaluepair_p.h>
#include <private/qqmlabstractbinding_p.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
QT_BEGIN_NAMESPACE
class QQmlContext;
class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlJavaScriptExpression,
- public QQmlAbstractExpression,
public QQmlAbstractBinding
{
+ friend class QQmlAbstractBinding;
public:
QQmlBinding(const QString &, QObject *, QQmlContext *);
QQmlBinding(const QQmlScriptString &, QObject *, QQmlContext *);
@@ -74,84 +73,62 @@ public:
QQmlBinding(const QString &, QObject *, QQmlContextData *,
const QString &url, quint16 lineNumber, quint16 columnNumber);
QQmlBinding(const QV4::Value &, QObject *, QQmlContextData *);
+ ~QQmlBinding();
void setTarget(const QQmlProperty &);
- void setTarget(QObject *, const QQmlPropertyData &, QQmlContextData *);
- QQmlProperty property() const;
+ void setTarget(QObject *, const QQmlPropertyData &);
void setNotifyOnValueChanged(bool);
- // Inherited from QQmlAbstractExpression
+ // Inherited from QQmlJavaScriptExpression
virtual void refresh();
- // "Inherited" from QQmlAbstractBinding
- static QString expression(const QQmlAbstractBinding *);
- static int propertyIndex(const QQmlAbstractBinding *);
- static QObject *object(const QQmlAbstractBinding *);
- static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- static void retargetBinding(QQmlAbstractBinding *, QObject *, int);
-
- void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags);
- void update(QQmlPropertyPrivate::WriteFlags flags);
- void update() { update(QQmlPropertyPrivate::DontRemoveBinding); }
-
- QString expression() const;
- QObject *object() const;
- int propertyIndex() const;
- void retargetBinding(QObject *, int);
+ // Inherited from QQmlAbstractBinding
+ virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
+ virtual QString expression() const;
+ void update(QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
typedef int Identifier;
- static Identifier Invalid;
+ enum {
+ Invalid = -1
+ };
QVariant evaluate();
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
-
-protected:
- friend class QQmlAbstractBinding;
- ~QQmlBinding();
+ virtual QString expressionIdentifier();
+ virtual void expressionChanged();
private:
- QV4::PersistentValue v4function;
-
inline bool updatingFlag() const;
inline void setUpdatingFlag(bool);
inline bool enabledFlag() const;
inline void setEnabledFlag(bool);
+ QQmlPropertyData getPropertyData() const;
- struct Retarget {
- QObject *target;
- int targetProperty;
- };
+ bool write(const QQmlPropertyData &core,
+ const QV4::Value &result, bool isUndefined,
+ QQmlPropertyPrivate::WriteFlags flags);
- QPointerValuePair<QObject, Retarget> m_coreObject;
- QQmlPropertyData m_core;
- // We store some flag bits in the following flag pointers.
- // m_ctxt:flag1 - updatingFlag
- // m_ctxt:flag2 - enabledFlag
- QFlagPointer<QQmlContextData> m_ctxt;
};
bool QQmlBinding::updatingFlag() const
{
- return m_ctxt.flag();
+ return m_target.flag();
}
void QQmlBinding::setUpdatingFlag(bool v)
{
- m_ctxt.setFlagValue(v);
+ m_target.setFlagValue(v);
}
bool QQmlBinding::enabledFlag() const
{
- return m_ctxt.flag2();
+ return m_target.flag2();
}
void QQmlBinding::setEnabledFlag(bool v)
{
- m_ctxt.setFlag2Value(v);
+ m_target.setFlag2Value(v);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 766e657c59..8b6f8afdce 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -47,7 +47,7 @@
#include <private/qqmlcompiler_p.h>
#include "qqmlinfo.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <QtCore/qstringbuilder.h>
#include <QtCore/qdebug.h>
@@ -55,59 +55,68 @@
QT_BEGIN_NAMESPACE
-static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = {
- QQmlBoundSignalExpression::expressionIdentifier,
- QQmlBoundSignalExpression::expressionChanged
-};
-
-QQmlBoundSignalExpression::ExtraData::ExtraData(const QString &handlerName, const QString &parameterString,
- const QString &expression, const QString &fileName,
- quint16 line, quint16 column)
- : m_handlerName(handlerName),
- m_parameterString(parameterString),
- m_expression(expression),
- m_sourceLocation(fileName, line, column)
-{
-}
-
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QQmlContextData *ctxt, QObject *scope, const QString &expression,
const QString &fileName, quint16 line, quint16 column,
const QString &handlerName,
const QString &parameterString)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_target(target),
- m_extra(new ExtraData(handlerName, parameterString, expression, fileName, line, column))
+ m_target(target)
{
- setExpressionFunctionValid(false);
- setInvalidParameterName(false);
-
init(ctxt, scope);
+
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
+ QV4::ExecutionEngine *v4 = ep->v4engine();
+
+ QString function;
+
+ // Add some leading whitespace to account for the binding's column offset.
+ // It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
+ function.fill(QChar(QChar::Space), qMax(column, (quint16)2) - 2);
+ function += QStringLiteral("(function ");
+ function += handlerName;
+ function += QLatin1Char('(');
+
+ if (parameterString.isEmpty()) {
+ QString error;
+ //TODO: look at using the property cache here (as in the compiler)
+ // for further optimization
+ QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
+ function += QQmlPropertyCache::signalParameterStringForJS(v4, signal.parameterNames(), &error);
+
+ if (!error.isEmpty()) {
+ qmlInfo(scopeObject()) << error;
+ return;
+ }
+ } else
+ function += parameterString;
+
+ function += QStringLiteral(") { ");
+ function += expression;
+ function += QStringLiteral(" })");
+
+ m_function.set(v4, evalFunction(context(), scopeObject(), function, fileName, line));
+
+ if (m_function.isNullOrUndefined())
+ return; // could not evaluate function. Not valid.
+
}
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QV4::Value &function)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_function(function.asObject()->engine(), function),
- m_target(target),
- m_extra(0)
+ m_target(target)
{
- setExpressionFunctionValid(true);
- setInvalidParameterName(false);
-
+ m_function.set(function.as<QV4::Object>()->engine(), function);
init(ctxt, scope);
}
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_target(target),
- m_extra(0)
+ m_target(target)
{
- setExpressionFunctionValid(true);
- setInvalidParameterName(false);
-
// It's important to call init first, because m_index gets remapped in case of cloned signals.
init(ctxt, scope);
@@ -117,9 +126,8 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error));
if (!error.isEmpty()) {
qmlInfo(scopeObject()) << error;
- setInvalidParameterName(true);
- } else
- setInvalidParameterName(false);
+ m_function.clear();
+ }
}
void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
@@ -134,34 +142,30 @@ void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
{
- delete m_extra.data();
}
-QString QQmlBoundSignalExpression::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlBoundSignalExpression::expressionIdentifier()
{
- QQmlBoundSignalExpression *This = static_cast<QQmlBoundSignalExpression *>(e);
- QQmlSourceLocation loc = This->sourceLocation();
+ QQmlSourceLocation loc = sourceLocation();
return loc.sourceFile + QLatin1Char(':') + QString::number(loc.line);
}
-void QQmlBoundSignalExpression::expressionChanged(QQmlJavaScriptExpression *)
+void QQmlBoundSignalExpression::expressionChanged()
{
// bound signals do not notify on change.
}
QQmlSourceLocation QQmlBoundSignalExpression::sourceLocation() const
{
- if (expressionFunctionValid()) {
- QV4::Function *f = function();
- Q_ASSERT(f);
+ QV4::Function *f = function();
+ if (f) {
QQmlSourceLocation loc;
loc.sourceFile = f->sourceFile();
loc.line = f->compiledFunction->location.line;
loc.column = f->compiledFunction->location.column;
return loc;
}
- Q_ASSERT(!m_extra.isNull());
- return m_extra->m_sourceLocation;
+ return QQmlSourceLocation();
}
QString QQmlBoundSignalExpression::expression() const
@@ -171,10 +175,8 @@ QString QQmlBoundSignalExpression::expression() const
QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
QV4::ScopedValue v(scope, m_function.value());
return v->toQStringNoThrow();
- } else {
- Q_ASSERT(!m_extra.isNull());
- return m_extra->m_expression;
}
+ return QString();
}
QV4::Function *QQmlBoundSignalExpression::function() const
@@ -194,108 +196,79 @@ void QQmlBoundSignalExpression::evaluate(void **a)
{
Q_ASSERT (context() && engine());
- if (invalidParameterName())
+ if (!expressionFunctionValid())
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- {
- if (!expressionFunctionValid()) {
- Q_ASSERT(!m_extra.isNull());
- QString expression;
-
- // Add some leading whitespace to account for the binding's column offset.
- // It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
- expression.fill(QChar(QChar::Space), qMax(m_extra->m_sourceLocation.column, (quint16)2) - 2);
- expression += QStringLiteral("(function ");
- expression += m_extra->m_handlerName;
- expression += QLatin1Char('(');
-
- if (m_extra->m_parameterString.isEmpty()) {
- QString error;
- //TODO: look at using the property cache here (as in the compiler)
- // for further optimization
- QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
- expression += QQmlPropertyCache::signalParameterStringForJS(scope.engine, signal.parameterNames(), &error);
-
- if (!error.isEmpty()) {
- qmlInfo(scopeObject()) << error;
- setInvalidParameterName(true);
- ep->dereferenceScarceResources();
- return;
- }
- } else
- expression += m_extra->m_parameterString;
-
- expression += QStringLiteral(") { ");
- expression += m_extra->m_expression;
- expression += QStringLiteral(" })");
-
- m_extra->m_expression.clear();
- m_extra->m_handlerName.clear();
- m_extra->m_parameterString.clear();
-
- m_function.set(scope.engine, evalFunction(context(), scopeObject(), expression,
- m_extra->m_sourceLocation.sourceFile, m_extra->m_sourceLocation.line, &m_extra->m_v8qmlscope));
-
- if (m_function.isNullOrUndefined()) {
- ep->dereferenceScarceResources();
- return; // could not evaluate function. Not valid.
- }
-
- setExpressionFunctionValid(true);
- }
- QVarLengthArray<int, 9> dummy;
- //TODO: lookup via signal index rather than method index as an optimization
- int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
- int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
- int argCount = argsTypes ? *argsTypes : 0;
-
- QV4::ScopedValue f(scope, m_function.value());
- QV4::ScopedCallData callData(scope, argCount);
- for (int ii = 0; ii < argCount; ++ii) {
- int type = argsTypes[ii + 1];
- //### ideally we would use metaTypeToJS, however it currently gives different results
- // for several cases (such as QVariant type and QObject-derived types)
- //args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
- if (type == QMetaType::QVariant) {
- callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
- } else if (type == QMetaType::Int) {
- //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
- callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
- } else if (type == qMetaTypeId<QQmlV4Handle>()) {
- callData->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
- } else if (ep->isQObject(type)) {
- if (!*reinterpret_cast<void* const *>(a[ii + 1]))
- callData->args[ii] = QV4::Primitive::nullValue();
- else
- callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1]));
- } else {
- callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1]));
- }
+ QVarLengthArray<int, 9> dummy;
+ //TODO: lookup via signal index rather than method index as an optimization
+ int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
+ int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
+ int argCount = argsTypes ? *argsTypes : 0;
+
+ QV4::ScopedCallData callData(scope, argCount);
+ for (int ii = 0; ii < argCount; ++ii) {
+ int type = argsTypes[ii + 1];
+ //### ideally we would use metaTypeToJS, however it currently gives different results
+ // for several cases (such as QVariant type and QObject-derived types)
+ //args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
+ if (type == QMetaType::QVariant) {
+ callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
+ } else if (type == QMetaType::Int) {
+ //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
+ callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
+ } else if (type == qMetaTypeId<QQmlV4Handle>()) {
+ callData->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
+ } else if (ep->isQObject(type)) {
+ if (!*reinterpret_cast<void* const *>(a[ii + 1]))
+ callData->args[ii] = QV4::Primitive::nullValue();
+ else
+ callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1]));
+ } else {
+ callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1]));
}
-
- QQmlJavaScriptExpression::evaluate(context(), f, callData, 0);
}
+
+ QQmlJavaScriptExpression::evaluate(callData, 0);
+
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
////////////////////////////////////////////////////////////////////////
-QQmlAbstractBoundSignal::QQmlAbstractBoundSignal()
-: m_prevSignal(0), m_nextSignal(0)
+
+/*! \internal
+ \a signal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
+ This is different from QMetaMethod::methodIndex().
+*/
+QQmlBoundSignal::QQmlBoundSignal(QObject *target, int signal, QObject *owner,
+ QQmlEngine *engine)
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlBoundSignal),
+ m_prevSignal(0), m_nextSignal(0),
+ m_expression(0)
{
+ addToObject(owner);
+
+ /*
+ If this is a cloned method, connect to the 'original'. For example,
+ for the signal 'void aSignal(int parameter = 0)', if the method
+ index refers to 'aSignal()', get the index of 'aSignal(int)'.
+ This ensures that 'parameter' will be available from QML.
+ */
+ signal = QQmlPropertyCache::originalClone(target, signal);
+ QQmlNotifierEndpoint::connect(target, signal, engine);
}
-QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal()
+QQmlBoundSignal::~QQmlBoundSignal()
{
removeFromObject();
}
-void QQmlAbstractBoundSignal::addToObject(QObject *obj)
+void QQmlBoundSignal::addToObject(QObject *obj)
{
Q_ASSERT(!m_prevSignal);
Q_ASSERT(obj);
@@ -308,7 +281,7 @@ void QQmlAbstractBoundSignal::addToObject(QObject *obj)
data->signalHandlers = this;
}
-void QQmlAbstractBoundSignal::removeFromObject()
+void QQmlBoundSignal::removeFromObject()
{
if (m_prevSignal) {
*m_prevSignal = m_nextSignal;
@@ -318,40 +291,6 @@ void QQmlAbstractBoundSignal::removeFromObject()
}
}
-/*! \internal
- \a signal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
- This is different from QMetaMethod::methodIndex().
-*/
-QQmlBoundSignal::QQmlBoundSignal(QObject *target, int signal, QObject *owner,
- QQmlEngine *engine)
-: m_expression(0), m_index(signal), m_isEvaluating(false)
-{
- addToObject(owner);
- setCallback(QQmlNotifierEndpoint::QQmlBoundSignal);
-
- /*
- If this is a cloned method, connect to the 'original'. For example,
- for the signal 'void aSignal(int parameter = 0)', if the method
- index refers to 'aSignal()', get the index of 'aSignal(int)'.
- This ensures that 'parameter' will be available from QML.
- */
- m_index = QQmlPropertyCache::originalClone(target, m_index);
- QQmlNotifierEndpoint::connect(target, m_index, engine);
-}
-
-QQmlBoundSignal::~QQmlBoundSignal()
-{
- m_expression = 0;
-}
-
-/*!
- Returns the signal index in the range returned by QObjectPrivate::signalIndex().
- This is different from QMetaMethod::methodIndex().
-*/
-int QQmlBoundSignal::index() const
-{
- return m_index;
-}
/*!
Returns the signal expression.
@@ -362,45 +301,26 @@ QQmlBoundSignalExpression *QQmlBoundSignal::expression() const
}
/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
+ Sets the signal expression to \a e.
- The QQmlBoundSignal instance adds a reference to \a e. The caller
- assumes ownership of the returned QQmlBoundSignalExpression reference.
+ The QQmlBoundSignal instance takes ownership of \a e (and does not add a reference).
*/
-QQmlBoundSignalExpressionPointer QQmlBoundSignal::setExpression(QQmlBoundSignalExpression *e)
+void QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
{
- QQmlBoundSignalExpressionPointer rv = m_expression;
- m_expression = e;
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
-}
-
-/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
-
- The QQmlBoundSignal instance takes ownership of \a e (and does not add a reference). The caller
- assumes ownership of the returned QQmlBoundSignalExpression reference.
-*/
-QQmlBoundSignalExpressionPointer QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
-{
- QQmlBoundSignalExpressionPointer rv = m_expression;
m_expression.take(e);
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
+ if (m_expression)
+ m_expression->setNotifyOnValueChanged(false);
}
void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
{
QQmlBoundSignal *s = static_cast<QQmlBoundSignal*>(e);
+
if (!s->m_expression)
return;
if (QQmlDebugService::isDebuggingEnabled())
- QV4DebugService::instance()->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(s->m_expression->target()->metaObject(), s->m_index).methodSignature()));
-
- s->m_isEvaluating = true;
+ QV4DebugService::instance()->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(s->m_expression->target()->metaObject(), s->signalIndex()).methodSignature()));
QQmlEngine *engine;
if (s->m_expression && (engine = s->m_expression->engine())) {
@@ -410,8 +330,6 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));
}
}
-
- s->m_isEvaluating = false;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index 8d677ea039..3742317484 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -47,7 +47,6 @@
#include <QtCore/qmetaobject.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qqmlboundsignalexpressionpointer_p.h>
#include <private/qqmlnotifier_p.h>
@@ -58,7 +57,7 @@
QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpression, public QQmlJavaScriptExpression, public QQmlRefCount
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlJavaScriptExpression, public QQmlRefCount
{
public:
QQmlBoundSignalExpression(QObject *target, int index,
@@ -73,9 +72,9 @@ public:
QQmlBoundSignalExpression(QObject *target, int index,
QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction);
- // "inherited" from QQmlJavaScriptExpression.
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
+ // inherited from QQmlJavaScriptExpression.
+ virtual QString expressionIdentifier();
+ virtual void expressionChanged();
// evaluation of a bound signal expression doesn't return any value
void evaluate(void **a);
@@ -92,80 +91,35 @@ private:
void init(QQmlContextData *ctxt, QObject *scope);
- bool expressionFunctionValid() const { return m_extra.flag(); }
- void setExpressionFunctionValid(bool v) { m_extra.setFlagValue(v); }
-
- bool invalidParameterName() const { return m_extra.flag2(); }
- void setInvalidParameterName(bool v) { m_extra.setFlag2Value(v); }
+ bool expressionFunctionValid() const { return !m_function.isNullOrUndefined(); }
int m_index;
- QV4::PersistentValue m_function;
-
QObject *m_target;
-
- // only needed when !expressionFunctionValid()
- struct ExtraData {
- ExtraData(const QString &handlerName, const QString &parameterString,
- const QString &expression, const QString &fileName,
- quint16 line, quint16 column);
- QString m_handlerName;
- QString m_parameterString;
- QString m_expression;
- QQmlSourceLocation m_sourceLocation;
- QV4::PersistentValue m_v8qmlscope;
- };
-
- // We store some flag bits in the following flag pointers.
- // flag - expressionFunctionValid
- // flag2 - invalidParameterName
- QFlagPointer<ExtraData> m_extra;
};
-class Q_QML_PRIVATE_EXPORT QQmlAbstractBoundSignal
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignal : public QQmlNotifierEndpoint
{
public:
- QQmlAbstractBoundSignal();
- virtual ~QQmlAbstractBoundSignal();
-
- virtual int index() const = 0;
- virtual QQmlBoundSignalExpression *expression() const = 0;
- virtual QQmlBoundSignalExpressionPointer setExpression(QQmlBoundSignalExpression *) = 0;
- virtual QQmlBoundSignalExpressionPointer takeExpression(QQmlBoundSignalExpression *) = 0;
- virtual bool isEvaluating() const = 0;
+ QQmlBoundSignal(QObject *target, int signal, QObject *owner, QQmlEngine *engine);
+ ~QQmlBoundSignal();
void removeFromObject();
-protected:
- void addToObject(QObject *owner);
+
+ QQmlBoundSignalExpression *expression() const;
+ void takeExpression(QQmlBoundSignalExpression *);
private:
- friend class QQmlData;
+ friend void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlPropertyPrivate;
+ friend class QQmlData;
friend class QQmlEngineDebugService;
- QQmlAbstractBoundSignal **m_prevSignal;
- QQmlAbstractBoundSignal *m_nextSignal;
-};
-class Q_QML_PRIVATE_EXPORT QQmlBoundSignal : public QQmlAbstractBoundSignal,
- public QQmlNotifierEndpoint
-{
-public:
- QQmlBoundSignal(QObject *target, int signal, QObject *owner, QQmlEngine *engine);
- virtual ~QQmlBoundSignal();
-
- int index() const;
-
- QQmlBoundSignalExpression *expression() const;
- QQmlBoundSignalExpressionPointer setExpression(QQmlBoundSignalExpression *);
- QQmlBoundSignalExpressionPointer takeExpression(QQmlBoundSignalExpression *);
+ void addToObject(QObject *owner);
- bool isEvaluating() const { return m_isEvaluating; }
-
-private:
- friend void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **);
+ QQmlBoundSignal **m_prevSignal;
+ QQmlBoundSignal *m_nextSignal;
QQmlBoundSignalExpressionPointer m_expression;
- int m_index;
- bool m_isEvaluating;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 9210610cec..d46f612e40 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -98,7 +98,6 @@ V4_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
\class QQmlComponent
\since 5.0
\inmodule QtQml
- \mainclass
\brief The QQmlComponent class encapsulates a QML component definition
@@ -1216,7 +1215,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
- if (!v->asObject() || v->asArrayObject()) {
+ if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
qmlInfo(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
@@ -1242,12 +1241,12 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (!valuemap->isUndefined()) {
QV4::ScopedObject qmlglobal(scope, args->qmlGlobal());
QV4::ScopedValue f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal));
- Q_ASSERT(f->asFunctionObject());
+ Q_ASSERT(f->as<QV4::FunctionObject>());
QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
+ callData->thisObject = v4->globalObject;
callData->args[0] = object;
callData->args[1] = valuemap;
- f->asFunctionObject()->call(callData);
+ f->as<QV4::FunctionObject>()->call(callData);
}
d->completeCreate();
@@ -1256,10 +1255,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QQmlData::get(rv)->explicitIndestructibleSet = false;
QQmlData::get(rv)->indestructible = false;
- if (!rv)
- args->setReturnValue(QV4::Encode::null());
- else
- args->setReturnValue(object->asReturnedValue());
+ args->setReturnValue(object->asReturnedValue());
}
/*!
@@ -1342,7 +1338,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
if (v->isNull()) {
- } else if (!v->asObject() || v->asArrayObject()) {
+ } else if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
qmlInfo(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
@@ -1390,14 +1386,14 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu
QV4::Scope scope(v4engine);
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate));
- Q_ASSERT(object->asObject());
+ Q_ASSERT(object->as<QV4::Object>());
if (!valuemap.isUndefined()) {
QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal);
QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4engine,
QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj));
QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4engine->globalObject();
+ callData->thisObject = v4engine->globalObject;
callData->args[0] = object;
callData->args[1] = valuemap;
f->call(callData);
@@ -1492,9 +1488,9 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
QV4::ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
- QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject()));
+ QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.as<Object>()));
QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
+ callData->thisObject = v4->globalObject;
callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
callData->args[1] = d()->valuemap;
f->call(callData);
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index 8c866c585a..121c83db5c 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -63,8 +63,8 @@ class Q_QML_EXPORT QQmlComponent : public QObject
Q_PROPERTY(QUrl url READ url CONSTANT)
public:
- Q_ENUMS(CompilationMode)
enum CompilationMode { PreferSynchronous, Asynchronous };
+ Q_ENUM(CompilationMode)
QQmlComponent(QObject *parent = 0);
QQmlComponent(QQmlEngine *, QObject *parent=0);
@@ -74,8 +74,8 @@ public:
QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = 0);
virtual ~QQmlComponent();
- Q_ENUMS(Status)
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
bool isNull() const;
@@ -125,7 +125,6 @@ private:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QQmlComponent::Status)
QML_DECLARE_TYPE(QQmlComponent)
QML_DECLARE_TYPEINFO(QQmlComponent, QML_HAS_ATTACHED_PROPERTIES)
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index f08f650913..56326df979 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -57,7 +57,6 @@ QQmlContextPrivate::QQmlContextPrivate()
/*!
\class QQmlContext
\brief The QQmlContext class defines a context within a QML engine.
- \mainclass
\inmodule QtQml
Contexts allow data to be exposed to the QML components instantiated by the
@@ -585,9 +584,9 @@ void QQmlContextData::clearContext()
{
emitDestruction();
- QQmlAbstractExpression *expression = expressions;
+ QQmlJavaScriptExpression *expression = expressions;
while (expression) {
- QQmlAbstractExpression *nextExpression = expression->m_nextExpression;
+ QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
expression->m_prevExpression = 0;
expression->m_nextExpression = 0;
@@ -652,9 +651,9 @@ void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership)
}
}
-void QQmlContextData::refreshExpressionsRecursive(QQmlAbstractExpression *expression)
+void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
{
- QQmlAbstractExpression::DeleteWatcher w(expression);
+ QQmlJavaScriptExpression::DeleteWatcher w(expression);
if (expression->m_nextExpression)
refreshExpressionsRecursive(expression->m_nextExpression);
@@ -808,7 +807,7 @@ QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
{
if (propertyNameCache.isEmpty()) {
propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
- for (QHash<int, int>::ConstIterator it = objectIndexToId.begin(), end = objectIndexToId.end();
+ for (QHash<int, int>::ConstIterator it = objectIndexToId.cbegin(), end = objectIndexToId.cend();
it != end; ++it) {
const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key());
const QString name = typeCompilationUnit->data->stringAt(obj->idIndex);
diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h
index c714846147..e69a2f8f69 100644
--- a/src/qml/qml/qqmlcontext.h
+++ b/src/qml/qml/qqmlcontext.h
@@ -72,6 +72,7 @@ public:
void setContextProperty(const QString &, QObject *);
void setContextProperty(const QString &, const QVariant &);
+ // ### Qt 6: no need for a mutable object, this should become a const QObject pointer
QString nameForObject(QObject *) const;
QUrl resolvedUrl(const QUrl &);
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index f5fd7d0a5c..95254d4baa 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -69,7 +69,7 @@ class QQmlExpression;
class QQmlEngine;
class QQmlExpression;
class QQmlExpressionPrivate;
-class QQmlAbstractExpression;
+class QQmlJavaScriptExpression;
class QQmlContextData;
class QQmlContextPrivate : public QObjectPrivate
@@ -171,7 +171,7 @@ public:
QQmlContextData **prevChild;
// Expressions that use this context
- QQmlAbstractExpression *expressions;
+ QQmlJavaScriptExpression *expressions;
// Doubly-linked list of objects that are owned by this context
QQmlData *contextObjects;
@@ -212,7 +212,7 @@ public:
private:
void refreshExpressionsRecursive(bool isGlobal);
- void refreshExpressionsRecursive(QQmlAbstractExpression *);
+ void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
~QQmlContextData() {}
};
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 5844eab54f..fd85b64ad1 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -38,13 +38,14 @@
#include <private/qqmlcontext_p.h>
#include <private/qv4engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4mm_p.h>
#include <private/qv4function_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qjsvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +61,6 @@ Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlCon
, isNullWrapper(false)
, context(context)
, scopeObject(scopeObject)
- , idObjectsWrapper(Q_NULLPTR)
{
}
@@ -93,49 +93,30 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url)
return w.asReturnedValue();
}
-QQmlContextData *QmlContextWrapper::callingContext(ExecutionEngine *v4)
-{
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, v4->qmlContextObject());
-
- return !!c ? c->getContext() : 0;
-}
-
QQmlContextData *QmlContextWrapper::getContext(const Value &value)
{
if (!value.isObject())
return 0;
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<Object>()->engine();
Scope scope(v4);
QV4::Scoped<QmlContextWrapper> c(scope, value);
return c ? c->getContext() : 0;
}
-void QmlContextWrapper::takeContextOwnership(const Value &qmlglobal)
-{
- Q_ASSERT(qmlglobal.isObject());
- QV4::ExecutionEngine *v4 = qmlglobal.asObject()->engine();
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, qmlglobal);
- Q_ASSERT(c);
- c->d()->ownsContext = true;
-}
-
-
-ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlContextWrapper>());
- QmlContextWrapper *resource = static_cast<QmlContextWrapper *>(m);
+ const QmlContextWrapper *resource = static_cast<const QmlContextWrapper *>(m);
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
// In V8 the JS global object would come _before_ the QML global object,
// so simulate that here.
bool hasProp;
- QV4::ScopedValue result(scope, v4->globalObject()->get(name, &hasProp));
+ QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp));
if (hasProp) {
if (hasProperty)
*hasProperty = hasProp;
@@ -145,7 +126,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
if (resource->d()->isNullWrapper)
return Object::get(m, name, hasProperty);
- if (QV4::QmlContextWrapper::callingContext(v4) != resource->d()->context)
+ if (v4->callingQmlContext() != resource->d()->context)
return Object::get(m, name, hasProperty);
result = Object::get(m, name, &hasProp);
@@ -209,7 +190,8 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
if (propertyIdx < context->idValueCount) {
- ep->captureProperty(&context->idValues[propertyIdx].bindings);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[propertyIdx].bindings);
if (hasProperty)
*hasProperty = true;
return QV4::QObjectWrapper::wrap(v4, context->idValues[propertyIdx]);
@@ -217,8 +199,8 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
QQmlContextPrivate *cp = context->asQQmlContextPrivate();
- ep->captureProperty(context->asQQmlContext(), -1,
- propertyIdx + cp->notifyIndex);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex);
const QVariant &value = cp->propertyValues.at(propertyIdx);
if (hasProperty)
@@ -278,10 +260,9 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
return;
QV4::Scoped<QmlContextWrapper> wrapper(scope, resource);
- PropertyAttributes attrs;
- Property *pd = wrapper->__getOwnProperty__(name, &attrs);
- if (pd) {
- wrapper->putValue(pd, attrs, value);
+ uint member = wrapper->internalClass()->find(name);
+ if (member < UINT_MAX) {
+ wrapper->putValue(wrapper->propertyAt(member), wrapper->internalClass()->propertyData[member], value);
return;
}
@@ -342,14 +323,6 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
Object::put(m, name, value);
}
-void QmlContextWrapper::markObjects(Heap::Base *m, ExecutionEngine *engine)
-{
- QmlContextWrapper::Data *This = static_cast<QmlContextWrapper::Data *>(m);
- if (This->idObjectsWrapper)
- This->idObjectsWrapper->mark(engine);
- Object::markObjects(m, engine);
-}
-
void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const CompiledData::Function *compiledFunction)
{
// Let the caller check and avoid the function call :)
@@ -358,7 +331,7 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
if (!ep)
return;
- QQmlEnginePrivate::PropertyCapture *capture = ep->propertyCapture;
+ QQmlPropertyCapture *capture = ep->propertyCapture;
if (!capture)
return;
@@ -393,15 +366,6 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
}
-ReturnedValue QmlContextWrapper::idObjectsArray()
-{
- if (!d()->idObjectsWrapper) {
- ExecutionEngine *v4 = engine();
- d()->idObjectsWrapper = v4->memoryManager->alloc<QQmlIdObjectsArray>(v4, this);
- }
- return d()->idObjectsWrapper->asReturnedValue();
-}
-
ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String *name)
{
if (!d()->context->imports)
@@ -423,20 +387,11 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String
return QJSValuePrivate::convertedToValue(engine(), siinfo->scriptApi(e));
}
-DEFINE_OBJECT_VTABLE(QQmlIdObjectsArray);
-
-Heap::QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper)
- : Heap::Object(engine)
- , contextWrapper(contextWrapper->d())
+ReturnedValue QmlContextWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
-}
-
-ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
-{
- Scope scope(static_cast<QV4::QQmlIdObjectsArray*>(m)->engine());
- Scoped<QQmlIdObjectsArray> This(scope, static_cast<QV4::QQmlIdObjectsArray*>(m));
- Scoped<QmlContextWrapper> contextWrapper(scope, This->d()->contextWrapper);
- QQmlContextData *context = contextWrapper->getContext();
+ const QV4::QmlContextWrapper *This = static_cast<const QV4::QmlContextWrapper *>(m);
+ Scope scope(This->engine());
+ QQmlContextData *context = This->getContext();
if (!context) {
if (hasProperty)
*hasProperty = false;
@@ -452,17 +407,10 @@ ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasPr
*hasProperty = true;
QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
- if (ep)
- ep->captureProperty(&context->idValues[index].bindings);
+ if (ep && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[index].bindings);
return QObjectWrapper::wrap(This->engine(), context->idValues[index].data());
}
-void QQmlIdObjectsArray::markObjects(Heap::Base *that, ExecutionEngine *engine)
-{
- QQmlIdObjectsArray::Data *This = static_cast<QQmlIdObjectsArray::Data *>(that);
- This->contextWrapper->mark(engine);
- Object::markObjects(that, engine);
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 52d8677103..e806077326 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qv4functionobject_p.h>
@@ -65,8 +65,6 @@ struct QmlContextWrapper;
namespace Heap {
-struct QQmlIdObjectsArray;
-
struct QmlContextWrapper : Object {
QmlContextWrapper(ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
~QmlContextWrapper();
@@ -76,12 +74,6 @@ struct QmlContextWrapper : Object {
QQmlGuardedContextData context;
QPointer<QObject> scopeObject;
- QQmlIdObjectsArray *idObjectsWrapper;
-};
-
-struct QQmlIdObjectsArray : Object {
- QQmlIdObjectsArray(QV4::ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper);
- QmlContextWrapper *contextWrapper;
};
}
@@ -94,8 +86,9 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
static ReturnedValue qmlScope(ExecutionEngine *e, QQmlContextData *ctxt, QObject *scope);
static ReturnedValue urlScope(ExecutionEngine *v4, const QUrl &);
- static QQmlContextData *callingContext(ExecutionEngine *v4);
- static void takeContextOwnership(const Value &qmlglobal);
+ void takeContextOwnership() {
+ d()->ownsContext = true;
+ }
inline QObject *getScopeObject() const { return d()->scopeObject; }
inline QQmlContextData *getContext() const { return d()->context; }
@@ -103,24 +96,14 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
void setReadOnly(bool b) { d()->readOnly = b; }
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
- static void markObjects(Heap::Base *m, ExecutionEngine *engine);
static void registerQmlDependencies(ExecutionEngine *context, const CompiledData::Function *compiledFunction);
- ReturnedValue idObjectsArray();
ReturnedValue qmlSingletonWrapper(ExecutionEngine *e, String *name);
-};
-
-struct QQmlIdObjectsArray : public Object
-{
- V4_OBJECT2(QQmlIdObjectsArray, Object)
-
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void markObjects(Heap::Base *that, ExecutionEngine *engine);
-
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
}
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 04c42b638d..3d2a76693a 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -48,8 +48,9 @@
#include <private/qtqmlglobal_p.h>
#include <private/qobject_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4persistent_p.h>
+#include <qjsengine.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,7 @@ class QQmlEngine;
class QQmlGuardImpl;
class QQmlCompiledData;
class QQmlAbstractBinding;
-class QQmlAbstractBoundSignal;
+class QQmlBoundSignal;
class QQmlContext;
class QQmlPropertyCache;
class QQmlContextData;
@@ -72,15 +73,7 @@ class QQmlNotifierEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlData : public QAbstractDeclarativeData
{
public:
- QQmlData()
- : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
- hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
- hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
- bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
- lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0),
- propertyCache(0), guards(0), extendedData(0) {
- init();
- }
+ QQmlData();
static inline void init() {
static bool initialized = false;
@@ -158,7 +151,7 @@ public:
QQmlContextData *outerContext;
QQmlAbstractBinding *bindings;
- QQmlAbstractBoundSignal *signalHandlers;
+ QQmlBoundSignal *signalHandlers;
// Linked list for QQmlContext::contextObjects
QQmlData *nextContextObject;
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 7f6310d58e..a45152e0a0 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -304,7 +304,9 @@ QList<QQmlError> QQmlDirParser::errors(const QString &uri) const
{
QUrl url(uri);
QList<QQmlError> errors;
- for (int i = 0; i < _errors.size(); ++i) {
+ const int numErrors = _errors.size();
+ errors.reserve(numErrors);
+ for (int i = 0; i < numErrors; ++i) {
const QQmlJS::DiagnosticMessage &msg = _errors.at(i);
QQmlError e;
QString description = msg.message;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 8cf3d2064d..fdce590873 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -225,7 +225,6 @@ void QQmlEnginePrivate::activateDesignerMode()
/*!
\class QQmlImageProviderBase
\brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
- \mainclass
\inmodule QtQml
Image providers must be registered with the QML engine. The only information the QML
@@ -247,6 +246,10 @@ void QQmlEnginePrivate::activateDesignerMode()
The QQuickImageProvider::requestPixmap() method will be called for all image requests.
\value Texture The Image Provider provides QSGTextureProvider based images.
The QQuickImageProvider::requestTexture() method will be called for all image requests.
+ \value ImageResponse The Image provider provides QQuickTextureFactory based images.
+ Should only be used in QQuickAsyncImageProvider or its subclasses.
+ The QQuickAsyncImageProvider::requestImageResponse() method will be called for all image requests.
+ Since Qt 5.6
\omitvalue Invalid
*/
@@ -595,8 +598,8 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
QQmlEnginePrivate::~QQmlEnginePrivate()
{
- typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator TypePropertyCacheIt;
- typedef QHash<int, QQmlCompiledData *>::Iterator CompositeTypesIt;
+ typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::const_iterator TypePropertyCacheIt;
+ typedef QHash<int, QQmlCompiledData *>::const_iterator CompositeTypesIt;
if (inProgressCreations)
qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
@@ -615,9 +618,9 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
if (incubationController) incubationController->d = 0;
incubationController = 0;
- for (TypePropertyCacheIt iter = typePropertyCache.begin(), end = typePropertyCache.end(); iter != end; ++iter)
+ for (TypePropertyCacheIt iter = typePropertyCache.cbegin(), end = typePropertyCache.cend(); iter != end; ++iter)
(*iter)->release();
- for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter) {
+ for (CompositeTypesIt iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) {
iter.value()->isRegisteredWithEngine = false;
// since unregisterInternalCompositeType() will not be called in this
@@ -654,6 +657,17 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
}
}
+QQmlData::QQmlData()
+ : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
+ hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
+ hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
+ bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
+ lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0),
+ propertyCache(0), guards(0), extendedData(0)
+{
+ init();
+}
+
void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
{
QQmlData *ddata = static_cast<QQmlData *>(d);
@@ -787,7 +801,7 @@ void QQmlData::markAsDeleted(QObject *o)
QQmlData::setQueuedForDeletion(o);
QObjectPrivate *p = QObjectPrivate::get(o);
- for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
+ for (QList<QObject *>::const_iterator it = p->children.constBegin(), end = p->children.constEnd(); it != end; ++it) {
QQmlData::markAsDeleted(*it);
}
}
@@ -812,14 +826,12 @@ void QQmlData::flushPendingBindingImpl(int coreIndex)
// Find the binding
QQmlAbstractBinding *b = bindings;
- while (b && *b->m_mePtr && b->propertyIndex() != coreIndex)
+ while (b && b->targetPropertyIndex() != coreIndex)
b = b->nextBinding();
- if (b && b->propertyIndex() == coreIndex) {
- b->clear();
+ if (b && b->targetPropertyIndex() == coreIndex)
b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
- }
}
bool QQmlEnginePrivate::baseModulesUninitialized = true;
@@ -874,7 +886,6 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
\since 5.0
\inmodule QtQml
\brief The QQmlEngine class provides an environment for instantiating QML components.
- \mainclass
Each QML component is instantiated in a QQmlContext.
QQmlContext's are essential for passing data to QML
@@ -1490,38 +1501,6 @@ QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
#endif
}
-/*!
- * \enum QQmlDebuggingEnabler::StartMode
- *
- * Defines the debug server's start behavior. You can interrupt QML engines starting while a debug
- * client is connecting, in order to set breakpoints in or profile startup code.
- *
- * \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
- * \value WaitForClient If a QML engine starts while the debug services are connecting,
- * interrupt it until they are done.
- */
-
-/*!
- * Enables debugging for QML engines created after calling this function. The debug server will
- * listen on \a port at \a hostName and block the QML engine until it receives a connection if
- * \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
- * specified it will listen on all available interfaces. You can only start one debug server at a
- * time. A debug server may have already been started if the -qmljsdebugger= command line argument
- * was given. This method returns \c true if a new debug server was successfully started, or
- * \c false otherwise.
- */
-bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
-{
-#ifndef QQML_NO_DEBUG_PROTOCOL
- return QQmlDebugServer::enable(port, port, mode == WaitForClient, hostName);
-#else
- Q_UNUSED(port);
- Q_UNUSED(block);
- Q_UNUSED(hostName);
- return false;
-#endif
-}
-
class QQmlDataExtended {
public:
QQmlDataExtended();
@@ -1651,12 +1630,11 @@ void QQmlData::destroyed(QObject *object)
QQmlAbstractBinding *binding = bindings;
while (binding) {
- QQmlAbstractBinding *next = binding->nextBinding();
binding->setAddedToObject(false);
- binding->setNextBinding(0);
- binding->destroy();
- binding = next;
+ binding = binding->nextBinding();
}
+ if (bindings && !bindings->ref.deref())
+ delete bindings;
if (compiledData) {
compiledData->release();
@@ -1669,9 +1647,9 @@ void QQmlData::destroyed(QObject *object)
deferredData = 0;
}
- QQmlAbstractBoundSignal *signalHandler = signalHandlers;
+ QQmlBoundSignal *signalHandler = signalHandlers;
while (signalHandler) {
- if (signalHandler->isEvaluating()) {
+ if (signalHandler->isNotifying()) {
// The object is being deleted during signal handler evaluation.
// This will cause a crash due to invalid memory access when the
// evaluation has completed.
@@ -1700,7 +1678,7 @@ void QQmlData::destroyed(QObject *object)
"%s", object, qPrintable(locationString));
}
- QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
+ QQmlBoundSignal *next = signalHandler->m_nextSignal;
signalHandler->m_prevSignal = 0;
signalHandler->m_nextSignal = 0;
delete signalHandler;
@@ -2113,8 +2091,7 @@ QString QQmlEngine::offlineStoragePath() const
return d->offlineStoragePath;
}
-QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
- QQmlError &error)
+QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion)
{
QList<QQmlType *> types;
@@ -2176,10 +2153,10 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
// Properties override:
// * other elements of the same name
+#if 0
bool overloadError = false;
QString overloadName;
-#if 0
for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
!overloadError && iter != raw->stringCache.end();
++iter) {
@@ -2196,7 +2173,6 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
overloadError = true;
}
}
-#endif
if (overloadError) {
if (hasCopied) raw->release();
@@ -2204,6 +2180,7 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
return 0;
}
+#endif
if (!hasCopied) raw->addref();
typePropertyCache.insert(qMakePair(type, minorVersion), raw);
@@ -2254,8 +2231,8 @@ bool QQmlEnginePrivate::isList(int t) const
int QQmlEnginePrivate::listType(int t) const
{
Locker locker(this);
- QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
- if (iter != m_qmlLists.end())
+ QHash<int, int>::ConstIterator iter = m_qmlLists.constFind(t);
+ if (iter != m_qmlLists.cend())
return *iter;
else
return QQmlMetaType::listType(t);
@@ -2264,8 +2241,8 @@ int QQmlEnginePrivate::listType(int t) const
QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return QQmlMetaObject((*iter)->rootPropertyCache);
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2276,8 +2253,8 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return QQmlMetaObject((*iter)->rootPropertyCache);
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2288,8 +2265,8 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return (*iter)->rootPropertyCache;
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2301,8 +2278,8 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return (*iter)->rootPropertyCache;
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index df673c1fd5..61a884279d 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -52,7 +52,9 @@ public:
Image,
Pixmap,
Texture,
- Invalid
+ Invalid,
+ ImageResponse
+ // ### Qt6: reorder these, and give Invalid a fixed large value
};
enum Flag {
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index f1fbad3cf8..1a317f6fbd 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -85,7 +85,6 @@ class QQmlImportDatabase;
class QNetworkReply;
class QNetworkAccessManager;
class QQmlNetworkAccessManagerFactory;
-class QQmlAbstractBinding;
class QQmlTypeNameCache;
class QQmlComponentAttached;
class QQmlCleanup;
@@ -95,6 +94,7 @@ class QQmlObjectCreator;
class QDir;
class QQmlIncubator;
class QQmlProfiler;
+class QQmlPropertyCapture;
// 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
@@ -123,16 +123,7 @@ public:
// is just qmlClearTypeRegistrations (which can't be called while an engine exists)
static bool baseModulesUninitialized;
- class PropertyCapture {
- public:
- inline virtual ~PropertyCapture() {}
- virtual void captureProperty(QQmlNotifier *) = 0;
- virtual void captureProperty(QObject *, int, int) = 0;
- };
-
- PropertyCapture *propertyCapture;
- inline void captureProperty(QQmlNotifier *);
- inline void captureProperty(QObject *, int, int);
+ QQmlPropertyCapture *propertyCapture;
QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
@@ -208,7 +199,7 @@ public:
inline static void deleteInEngineThread(QQmlEngine *, T *);
// These methods may be called from the loader thread
- inline QQmlPropertyCache *cache(QQmlType *, int, QQmlError &error);
+ inline QQmlPropertyCache *cache(QQmlType *, int);
using QJSEnginePrivate::cache;
// These methods may be called from the loader thread
@@ -262,7 +253,7 @@ public:
private:
// Must be called locked
- QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
+ QQmlPropertyCache *createCache(QQmlType *, int);
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
@@ -346,7 +337,7 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQmlError &error)
+QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion)
{
Q_ASSERT(type);
@@ -355,7 +346,7 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQ
Locker locker(this);
QQmlPropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
- if (!rv) rv = createCache(type, minorVersion, error);
+ if (!rv) rv = createCache(type, minorVersion);
return rv;
}
@@ -414,18 +405,6 @@ QQmlEnginePrivate *QQmlEnginePrivate::get(QV4::ExecutionEngine *e)
return get(qmlEngine);
}
-void QQmlEnginePrivate::captureProperty(QQmlNotifier *n)
-{
- if (propertyCapture)
- propertyCapture->captureProperty(n);
-}
-
-void QQmlEnginePrivate::captureProperty(QObject *o, int c, int n)
-{
- if (propertyCapture)
- propertyCapture->captureProperty(o, c, n);
-}
-
void QQmlEnginePrivate::setDebugChangesCache(const QHash<QUrl, QByteArray> &changes)
{
Locker locker(this);
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 35e0bc8c64..332b99ee8f 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -45,13 +45,8 @@
QT_BEGIN_NAMESPACE
-static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = {
- QQmlExpressionPrivate::expressionIdentifier,
- QQmlExpressionPrivate::expressionChanged
-};
-
QQmlExpressionPrivate::QQmlExpressionPrivate()
-: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable),
+: QQmlJavaScriptExpression(),
expressionFunctionValid(true),
line(0), column(0)
{
@@ -65,7 +60,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb
{
expression = expr;
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(me);
expressionFunctionValid = false;
}
@@ -74,9 +69,9 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFu
{
expressionFunctionValid = true;
QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
- function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction));
+ m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction));
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(me);
}
@@ -246,18 +241,12 @@ void QQmlExpression::setExpression(const QString &expression)
// Must be called with a valid handle scope
QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined)
{
- Q_Q(QQmlExpression);
-
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(q->engine())->v4engine();
-
if (!expressionFunctionValid) {
- function.set(v4, qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope));
+ createQmlBinding(context(), scopeObject(), expression, url, line);
expressionFunctionValid = true;
}
- QV4::Scope scope(v4);
- QV4::ScopedValue f(scope, function.value());
- return evaluate(context(), f, isUndefined);
+ return evaluate(isUndefined);
}
QVariant QQmlExpressionPrivate::value(bool *isUndefined)
@@ -432,22 +421,15 @@ QQmlError QQmlExpression::error() const
calling QQmlExpression::evaluate()) before this signal will be emitted.
*/
-void QQmlExpressionPrivate::expressionChanged(QQmlJavaScriptExpression *e)
-{
- QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
- This->expressionChanged();
-}
-
void QQmlExpressionPrivate::expressionChanged()
{
Q_Q(QQmlExpression);
emit q->valueChanged();
}
-QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlExpressionPrivate::expressionIdentifier()
{
- QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
- return QLatin1Char('"') + This->expression + QLatin1Char('"');
+ return QLatin1Char('"') + expression + QLatin1Char('"');
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index d8da387878..2303539194 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -52,7 +52,6 @@
#include <private/qflagpointer_p.h>
#include <private/qdeletewatcher_p.h>
#include <private/qpointervaluepair_p.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
QT_BEGIN_NAMESPACE
@@ -60,8 +59,7 @@ QT_BEGIN_NAMESPACE
class QQmlExpression;
class QString;
class QQmlExpressionPrivate : public QObjectPrivate,
- public QQmlJavaScriptExpression,
- public QQmlAbstractExpression
+ public QQmlJavaScriptExpression
{
Q_DECLARE_PUBLIC(QQmlExpression)
public:
@@ -82,16 +80,12 @@ public:
bool expressionFunctionValid:1;
- // "Inherited" from QQmlJavaScriptExpression
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
+ // Inherited from QQmlJavaScriptExpression
+ virtual QString expressionIdentifier();
virtual void expressionChanged();
QString expression;
- QV4::PersistentValue qmlscope;
- QV4::PersistentValue function;
-
QString url; // This is a QString for a reason. QUrls are slooooooow...
quint16 line;
quint16 column;
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 5a54609e12..87ee8078f4 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -169,6 +169,7 @@ QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeNa
} // namespace
+#ifndef QT_NO_LIBRARY
struct RegisteredPlugin {
QString uri;
QPluginLoader* loader;
@@ -193,6 +194,7 @@ void qmlClearEnginePlugins()
}
typedef QPair<QStaticPlugin, QJsonArray> StaticPluginPair;
+#endif
class QQmlImportNamespace
{
@@ -292,9 +294,10 @@ public:
const QString &uri, const QString &url,
int vmaj, int vmin, QV4::CompiledData::Import::ImportType type,
QList<QQmlError> *errors, bool lowPrecedence = false);
-
+#ifndef QT_NO_LIBRARY
bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri,
const QString &qmldirPath, QList<QQmlError> *errors);
+#endif
};
/*!
@@ -826,6 +829,7 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr
}
+#ifndef QT_NO_LIBRARY
/*!
Get all static plugins that are QML plugins and has a meta data URI that begins with \a uri.
Note that if e.g uri == "a", and different plugins have meta data "a", "a.2.1", "a.b.c", all
@@ -869,6 +873,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
}
return true;
}
+#endif
/*!
Import an extension defined by a qmldir file.
@@ -995,6 +1000,13 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
}
#else
+ Q_UNUSED(qmldirFilePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(vmin);
+ Q_UNUSED(database);
+ Q_UNUSED(qmldir);
+ Q_UNUSED(errors);
return false;
#endif // QT_NO_LIBRARY
return true;
@@ -1931,6 +1943,12 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
return true;
#else
+ Q_UNUSED(instance);
+ Q_UNUSED(basePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(typeNamespace);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(errors);
return false;
#endif
}
@@ -2011,6 +2029,11 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
return true;
#else
+ Q_UNUSED(filePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(typeNamespace);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(errors);
return false;
#endif
}
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 02bd1c4b83..5f30eac066 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -35,7 +35,7 @@
#include <private/qqmlexpression_p.h>
#include <private/qqmlcontextwrapper_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4errorobject_p.h>
@@ -83,13 +83,22 @@ void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionEngine *engine)
}
-QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v)
-: m_vtable(v)
+QQmlJavaScriptExpression::QQmlJavaScriptExpression()
+ : m_error(0),
+ m_context(0),
+ m_prevExpression(0),
+ m_nextExpression(0)
{
}
QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
{
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ }
+
clearGuards();
if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion.
m_scopeObject.asT2()->_s = 0;
@@ -106,40 +115,62 @@ void QQmlJavaScriptExpression::resetNotifyOnValueChanged()
clearGuards();
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
- const QV4::Value &function, bool *isUndefined)
+void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(context->engine);
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ m_prevExpression = 0;
+ m_nextExpression = 0;
+ }
+
+ m_context = context;
+
+ if (context) {
+ m_nextExpression = context->expressions;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = &m_nextExpression;
+ m_prevExpression = &context->expressions;
+ context->expressions = this;
+ }
+}
+
+void QQmlJavaScriptExpression::refresh()
+{
+}
+
+QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
+{
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_context->engine);
QV4::Scope scope(v4);
QV4::ScopedCallData callData(scope);
- return evaluate(context, function, callData, isUndefined);
+ return evaluate(callData, isUndefined);
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
- const QV4::Value &function,
- QV4::CallData *callData,
- bool *isUndefined)
+QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
{
- Q_ASSERT(context && context->engine);
+ Q_ASSERT(m_context && m_context->engine);
- if (function.isUndefined()) {
+ QV4::Value *f = m_function.valueRef();
+ if (!f || f->isUndefined()) {
if (isUndefined)
*isUndefined = true;
return QV4::Encode::undefined();
}
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine);
// All code that follows must check with watcher before it accesses data members
// incase we have been deleted.
DeleteWatcher watcher(this);
Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
- GuardCapture capture(context->engine, this, &watcher);
+ QQmlPropertyCapture capture(m_context->engine, this, &watcher);
- QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture;
- ep->propertyCapture = notifyOnValueChanged()?&capture:0;
+ QQmlPropertyCapture *lastPropertyCapture = ep->propertyCapture;
+ ep->propertyCapture = notifyOnValueChanged() ? &capture : 0;
if (notifyOnValueChanged())
@@ -148,14 +179,14 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
- callData->thisObject = v4->globalObject();
+ callData->thisObject = v4->globalObject;
if (scopeObject()) {
QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject()));
if (value->isObject())
callData->thisObject = value;
}
- result = function.asFunctionObject()->call(callData);
+ result = f->as<QV4::FunctionObject>()->call(callData);
if (scope.hasException()) {
if (watcher.wasDeleted())
scope.engine->catchException(); // ignore exception
@@ -178,7 +209,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
capture.errorString = 0;
}
- while (Guard *g = capture.guards.takeFirst())
+ while (QQmlJavaScriptExpressionGuard *g = capture.guards.takeFirst())
g->Delete();
ep->propertyCapture = lastPropertyCapture;
@@ -186,7 +217,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
return result->asReturnedValue();
}
-void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
+void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
{
if (watcher->wasDeleted())
return;
@@ -196,13 +227,13 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
while (!guards.isEmpty() && !guards.first()->isConnected(n))
guards.takeFirst()->Delete();
- Guard *g = 0;
+ QQmlJavaScriptExpressionGuard *g = 0;
if (!guards.isEmpty()) {
g = guards.takeFirst();
g->cancelNotify();
Q_ASSERT(g->isConnected(n));
} else {
- g = Guard::New(expression, engine);
+ g = QQmlJavaScriptExpressionGuard::New(expression, engine);
g->connect(n);
}
@@ -213,7 +244,7 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
\a n is in the signal index range (see QObjectPrivate::signalIndex()).
*/
-void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n)
+void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n)
{
if (watcher->wasDeleted())
return;
@@ -223,7 +254,7 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
if (!errorString) {
errorString = new QStringList;
QString preamble = QLatin1String("QQmlExpression: Expression ") +
- expression->m_vtable->expressionIdentifier(expression) +
+ expression->expressionIdentifier() +
QLatin1String(" depends on non-NOTIFYable properties:");
errorString->append(preamble);
}
@@ -242,13 +273,13 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
while (!guards.isEmpty() && !guards.first()->isConnected(o, n))
guards.takeFirst()->Delete();
- Guard *g = 0;
+ QQmlJavaScriptExpressionGuard *g = 0;
if (!guards.isEmpty()) {
g = guards.takeFirst();
g->cancelNotify();
Q_ASSERT(g->isConnected(o, n));
} else {
- g = Guard::New(expression, engine);
+ g = QQmlJavaScriptExpressionGuard::New(expression, engine);
g->connect(o, n, engine);
}
@@ -258,31 +289,31 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
void QQmlJavaScriptExpression::clearError()
{
- if (m_vtable.hasValue()) {
- m_vtable.value().clearError();
- m_vtable.value().removeError();
- }
+ if (m_error)
+ delete m_error;
+ m_error = 0;
}
QQmlError QQmlJavaScriptExpression::error(QQmlEngine *engine) const
{
Q_UNUSED(engine);
- if (m_vtable.hasValue())
- return m_vtable.constValue()->error();
+ if (m_error)
+ return m_error->error();
else
return QQmlError();
}
QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
{
- return &m_vtable.value();
+ if (!m_error)
+ m_error = new QQmlDelayedError;
+ return m_error;
}
QV4::ReturnedValue
QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObject,
- const QString &code, const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope)
+ const QString &code, const QString &filename, quint16 line)
{
QQmlEngine *engine = ctxt->engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
@@ -308,14 +339,11 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
ep->warning(error);
return QV4::Encode::undefined();
}
- if (qmlscope)
- qmlscope->set(v4, qmlScopeObject);
return result->asReturnedValue();
}
-QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
- const QString &code, const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope)
+void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
+ const QString &code, const QString &filename, quint16 line)
{
QQmlEngine *engine = ctxt->engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
@@ -339,17 +367,15 @@ QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, Q
error.setUrl(QUrl::fromLocalFile(filename));
error.setObject(qmlScope);
ep->warning(error);
- return QV4::Encode::undefined();
+ result = QV4::Encode::undefined();
}
- if (qmlscope)
- qmlscope->set(v4, qmlScopeObject);
- return result->asReturnedValue();
+ m_function.set(v4, result);
}
void QQmlJavaScriptExpression::clearGuards()
{
- while (Guard *g = activeGuards.takeFirst())
+ while (QQmlJavaScriptExpressionGuard *g = activeGuards.takeFirst())
g->Delete();
}
@@ -358,7 +384,7 @@ void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *e, void **)
QQmlJavaScriptExpression *expression =
static_cast<QQmlJavaScriptExpressionGuard *>(e)->expression;
- expression->m_vtable->expressionChanged(expression);
+ expression->expressionChanged();
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 989d5a0b0d..dfcf8b2d68 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -89,23 +89,17 @@ private:
QQmlDelayedError **prevError;
};
-class QQmlJavaScriptExpression
+class Q_QML_PRIVATE_EXPORT QQmlJavaScriptExpression
{
public:
- // Although this looks crazy, we implement our own "vtable" here, rather than relying on
- // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage
- // location that is use for the vtable to also store the rarely used delayed error.
- // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in
- // memory for every expression.
- struct VTable {
- QString (*expressionIdentifier)(QQmlJavaScriptExpression *);
- void (*expressionChanged)(QQmlJavaScriptExpression *);
- };
+ QQmlJavaScriptExpression();
+ virtual ~QQmlJavaScriptExpression();
- QQmlJavaScriptExpression(VTable *vtable);
+ virtual QString expressionIdentifier() = 0;
+ virtual void expressionChanged() = 0;
- QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, bool *isUndefined);
- QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, QV4::CallData *callData, bool *isUndefined);
+ QV4::ReturnedValue evaluate(bool *isUndefined);
+ QV4::ReturnedValue evaluate(QV4::CallData *callData, bool *isUndefined);
inline bool notifyOnValueChanged() const;
@@ -115,6 +109,13 @@ public:
inline QObject *scopeObject() const;
inline void setScopeObject(QObject *v);
+ bool isValid() const { return context() != 0; }
+
+ QQmlContextData *context() const { return m_context; }
+ void setContext(QQmlContextData *context);
+
+ virtual void refresh();
+
class DeleteWatcher {
public:
inline DeleteWatcher(QQmlJavaScriptExpression *);
@@ -136,46 +137,50 @@ public:
static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
const QString &code, const QString &filename,
- quint16 line,
- QV4::PersistentValue *qmlscope = 0);
- // doesn't require rewriting the expression
- static QV4::ReturnedValue qmlBinding(QQmlContextData *ctxt, QObject *scope,
- const QString &code,
- const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope = 0);
+ quint16 line);
protected:
- ~QQmlJavaScriptExpression();
+ void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
private:
- typedef QQmlJavaScriptExpressionGuard Guard;
+ friend class QQmlContextData;
+ friend class QQmlPropertyCapture;
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
- struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
- GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, DeleteWatcher *w)
- : engine(engine), expression(e), watcher(w), errorString(0) { }
-
- ~GuardCapture() {
- Q_ASSERT(guards.isEmpty());
- Q_ASSERT(errorString == 0);
- }
-
- virtual void captureProperty(QQmlNotifier *);
- virtual void captureProperty(QObject *, int, int);
-
- QQmlEngine *engine;
- QQmlJavaScriptExpression *expression;
- DeleteWatcher *watcher;
- QFieldList<Guard, &Guard::next> guards;
- QStringList *errorString;
- };
-
- QPointerValuePair<VTable, QQmlDelayedError> m_vtable;
+ QQmlDelayedError *m_error;
// We store some flag bits in the following flag pointers.
// activeGuards:flag1 - notifyOnValueChanged
// activeGuards:flag2 - useSharedContext
QBiPointer<QObject, DeleteWatcher> m_scopeObject;
- QForwardFieldList<Guard, &Guard::next> activeGuards;
+ QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
+
+ QQmlContextData *m_context;
+ QQmlJavaScriptExpression **m_prevExpression;
+ QQmlJavaScriptExpression *m_nextExpression;
+
+protected:
+ QV4::PersistentValue m_function;
+};
+
+class QQmlPropertyCapture
+{
+public:
+ QQmlPropertyCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, QQmlJavaScriptExpression::DeleteWatcher *w)
+ : engine(engine), expression(e), watcher(w), errorString(0) { }
+
+ ~QQmlPropertyCapture() {
+ Q_ASSERT(guards.isEmpty());
+ Q_ASSERT(errorString == 0);
+ }
+
+ void captureProperty(QQmlNotifier *);
+ void captureProperty(QObject *, int, int);
+
+ QQmlEngine *engine;
+ QQmlJavaScriptExpression *expression;
+ QQmlJavaScriptExpression::DeleteWatcher *watcher;
+ QFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> guards;
+ QStringList *errorString;
};
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
@@ -222,18 +227,18 @@ void QQmlJavaScriptExpression::setScopeObject(QObject *v)
bool QQmlJavaScriptExpression::hasError() const
{
- return m_vtable.hasValue() && m_vtable.constValue()->isValid();
+ return m_error && m_error->isValid();
}
bool QQmlJavaScriptExpression::hasDelayedError() const
{
- return m_vtable.hasValue();
+ return m_error;
}
QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e)
-: expression(e), next(0)
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlJavaScriptExpressionGuard),
+ expression(e), next(0)
{
- setCallback(QQmlNotifierEndpoint::QQmlJavaScriptExpressionGuard);
}
QQmlJavaScriptExpressionGuard *
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index bcb1e72f0b..e9ecefb56d 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -92,13 +92,13 @@ QVariant QmlListWrapper::toVariant() const
}
-ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlListWrapper>());
- QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
+ const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
- if (name->equals(v4->id_length) && !w->d()->object.isNull()) {
+ if (name->equals(v4->id_length()) && !w->d()->object.isNull()) {
quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
return Primitive::fromUInt32(count).asReturnedValue();
}
@@ -110,12 +110,12 @@ ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
return Object::get(m, name, hasProperty);
}
-ReturnedValue QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_UNUSED(hasProperty);
Q_ASSERT(m->as<QmlListWrapper>());
- QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
+ const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 3590bcb1c9..7e305b9e43 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -50,7 +50,7 @@
#include <QtQml/qqmllist.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -81,8 +81,8 @@ struct Q_QML_EXPORT QmlListWrapper : Object
QVariant toVariant() const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
};
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 62b5b76ede..7f49798da6 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -65,13 +65,13 @@ static bool isLocaleObject(const QV4::Value &val)
void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated);
}
QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ctx)
@@ -81,7 +81,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ct
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->thisObject().asDateObject();
+ QV4::DateObject *date = ctx->thisObject().as<DateObject>();
if (!date)
return QV4::DatePrototype::method_toLocaleString(ctx);
@@ -125,7 +125,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->thisObject().asDateObject();
+ QV4::DateObject *date = ctx->thisObject().as<DateObject>();
if (!date)
return QV4::DatePrototype::method_toLocaleTimeString(ctx);
@@ -170,7 +170,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext
QV4::Scope scope(ctx);
- QV4::DateObject *dateObj = ctx->thisObject().asDateObject();
+ QV4::DateObject *dateObj = ctx->thisObject().as<DateObject>();
if (!dateObj)
return QV4::DatePrototype::method_toLocaleDateString(ctx);
@@ -347,9 +347,9 @@ QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *c
void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
- engine->numberCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
+ engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
+ engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
}
QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *ctx)
@@ -815,15 +815,15 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
{
- engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
+ engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
}
QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx)
{
- if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].asStringObject()))
+ if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].as<StringObject>()))
return QV4::StringPrototype::method_localeCompare(ctx);
- if (!ctx->thisObject().isString() && !ctx->thisObject().asStringObject())
+ if (!ctx->thisObject().isString() && !ctx->thisObject().as<StringObject>())
return QV4::StringPrototype::method_localeCompare(ctx);
QString thisString = ctx->thisObject().toQStringNoThrow();
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index d4436482cf..cb9fe9bbef 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -74,10 +74,6 @@ private:
class Q_AUTOTEST_EXPORT QQmlLocale
{
Q_GADGET
- Q_ENUMS(MeasurementSystem)
- Q_ENUMS(FormatType)
- Q_ENUMS(CurrencySymbolFormat)
- Q_ENUMS(DayOfWeek)
public:
~QQmlLocale();
@@ -88,16 +84,19 @@ public:
ImperialUSSystem = QLocale::ImperialUSSystem,
ImperialUKSystem = QLocale::ImperialUKSystem
};
+ Q_ENUM(MeasurementSystem)
enum FormatType {
LongFormat = QLocale::LongFormat,
ShortFormat = QLocale::ShortFormat,
NarrowFormat = QLocale::NarrowFormat
};
+ Q_ENUM(FormatType)
enum CurrencySymbolFormat {
CurrencyIsoCode = QLocale::CurrencyIsoCode,
CurrencySymbol = QLocale::CurrencySymbol,
CurrencyDisplayName = QLocale::CurrencyDisplayName
};
+ Q_ENUM(CurrencySymbolFormat)
// Qt defines Sunday as 7, but JS Date assigns Sunday 0
enum DayOfWeek {
Sunday = 0,
@@ -108,6 +107,7 @@ public:
Friday = Qt::Friday,
Saturday = Qt::Saturday
};
+ Q_ENUM(DayOfWeek)
static QV4::ReturnedValue locale(QV4::ExecutionEngine *engine, const QString &localeName);
static QV4::ReturnedValue wrap(QV4::ExecutionEngine *engine, const QLocale &locale);
@@ -137,7 +137,7 @@ struct QQmlLocaleData : public QV4::Object
V4_NEEDS_DESTROY
static QLocale *getThisLocale(QV4::CallContext *ctx) {
- QV4::Object *o = ctx->thisObject().asObject();
+ QV4::Object *o = ctx->thisObject().as<Object>();
QQmlLocaleData *thisObject = o ? o->as<QQmlLocaleData>() : 0;
if (!thisObject) {
ctx->engine()->throwTypeError();
diff --git a/src/qml/qml/qqmlmemoryprofiler.cpp b/src/qml/qml/qqmlmemoryprofiler.cpp
index cdd60e2dec..531666340b 100644
--- a/src/qml/qml/qqmlmemoryprofiler.cpp
+++ b/src/qml/qml/qqmlmemoryprofiler.cpp
@@ -63,11 +63,13 @@ static qmlmemprofile_pop_location *memprofile_pop_location;
static qmlmemprofile_save *memprofile_save;
static qmlmemprofile_is_enabled *memprofile_is_enabled;
+#ifndef QT_NO_LIBRARY
extern QFunctionPointer qt_linux_find_symbol_sys(const char *symbol);
+#endif
static bool openLibrary()
{
-#ifdef Q_OS_LINUX
+#if defined(Q_OS_LINUX) && !defined(QT_NO_LIBRARY)
if (state == Unloaded) {
memprofile_stats = (qmlmemprofile_stats *) qt_linux_find_symbol_sys("qmlmemprofile_stats");
memprofile_clear = (qmlmemprofile_clear *) qt_linux_find_symbol_sys("qmlmemprofile_clear");
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 2f7834fa41..55df65e607 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1107,7 +1107,9 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
data->uriToModule.clear();
QQmlEnginePrivate::baseModulesUninitialized = true; //So the engine re-registers its types
+#ifndef QT_NO_LIBRARY
qmlClearEnginePlugins();
+#endif
}
int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
@@ -1437,8 +1439,8 @@ bool QQmlMetaType::isAnyModule(const QString &uri)
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
- iter != data->uriToModule.end(); ++iter) {
+ for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.cbegin();
+ iter != data->uriToModule.cend(); ++iter) {
if ((*iter)->module() == uri)
return true;
}
@@ -1715,7 +1717,7 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name);
- while (it != data->nameToType.end() && it.key() == name) {
+ while (it != data->nameToType.cend() && it.key() == name) {
// XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
if (version_major < 0 || module.isEmpty() || (*it)->availableInVersion(module, version_major,version_minor))
return (*it);
@@ -1749,7 +1751,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject);
- while (it != data->metaObjectToType.end() && it.key() == metaObject) {
+ while (it != data->metaObjectToType.cend() && it.key() == metaObject) {
QQmlType *t = *it;
if (version_major < 0 || module.isEmpty() || t->availableInVersion(module, version_major,version_minor))
return t;
@@ -1820,8 +1822,9 @@ QList<QString> QQmlMetaType::qmlTypeNames()
QQmlMetaTypeData *data = metaTypeData();
QList<QString> names;
- QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin();
- while (it != data->nameToType.end()) {
+ names.reserve(data->nameToType.count());
+ QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.cbegin();
+ while (it != data->nameToType.cend()) {
names += (*it)->qmlTypeName();
++it;
}
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index 2a35dcda12..bd2c0e6506 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -61,9 +61,6 @@ class QQmlEngine;
class QQmlNotifierEndpoint
{
public:
- inline QQmlNotifierEndpoint();
- inline ~QQmlNotifierEndpoint();
-
// QQmlNotifierEndpoint can only invoke one of a set of pre-defined callbacks.
// To add another callback, extend this enum and add the callback to the top
// of qqmlnotifier.cpp. Four bits are reserved for the callback, so there can
@@ -75,7 +72,8 @@ public:
QQmlVMEMetaObjectEndpoint = 3
};
- inline void setCallback(Callback c) { callback = c; }
+ inline QQmlNotifierEndpoint(Callback callback);
+ inline ~QQmlNotifierEndpoint();
inline bool isConnected();
inline bool isConnected(QObject *source, int sourceSignal);
@@ -88,6 +86,8 @@ public:
inline bool isNotifying() const;
inline void cancelNotify();
+ inline int signalIndex() const { return sourceSignal; }
+
private:
friend class QQmlData;
friend class QQmlNotifier;
@@ -136,8 +136,8 @@ void QQmlNotifier::notify()
if (endpoints) emitNotify(endpoints, args);
}
-QQmlNotifierEndpoint::QQmlNotifierEndpoint()
-: senderPtr(0), callback(None), sourceSignal(-1), next(0), prev(0)
+QQmlNotifierEndpoint::QQmlNotifierEndpoint(Callback callback)
+: senderPtr(0), callback(callback), sourceSignal(-1), next(0), prev(0)
{
}
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 3c2f3690b9..0b977f2551 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -62,14 +62,6 @@ struct ActiveOCRestorer
};
}
-static void removeBindingOnProperty(QObject *o, int index)
-{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
- if (binding) binding->destroy();
-}
-
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext)
: phase(Startup)
, compiledData(compiledData)
@@ -137,11 +129,6 @@ QQmlObjectCreator::~QQmlObjectCreator()
{
QQmlObjectCreatorRecursionWatcher watcher(this);
}
- for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) {
- QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i);
- if (b)
- b->m_mePtr = 0;
- }
for (int i = 0; i < sharedState->allParserStatusCallbacks.count(); ++i) {
QQmlParserStatus *ps = sharedState->allParserStatusCallbacks.at(i);
if (ps)
@@ -660,15 +647,12 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
// ### this is best done through type-compile-time binding skip lists.
if (_valueTypeProperty) {
- QQmlAbstractBinding *binding =
- QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex, -1);
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex);
- if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
- QQmlPropertyPrivate::setBinding(_bindingTarget, _valueTypeProperty->coreIndex, -1, 0);
- binding->destroy();
+ if (binding && !binding->isValueTypeProxy()) {
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, _valueTypeProperty->coreIndex);
} else if (binding) {
- QQmlValueTypeProxyBinding *proxy =
- static_cast<QQmlValueTypeProxyBinding *>(binding);
+ QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
if (qmlTypeForObject(_bindingTarget)) {
quint32 bindingSkipList = 0;
@@ -731,7 +715,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
// ### resolve this at compile time
if (property && property->propType == qMetaTypeId<QQmlScriptString>()) {
QQmlScriptString ss(binding->valueAsScriptString(qmlUnit), context->asQQmlContext(), _scopeObject);
- ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : QQmlBinding::Invalid;
+ ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
ss.d.data()->lineNumber = binding->location.line;
ss.d.data()->columnNumber = binding->location.column;
ss.d.data()->isStringLiteral = binding->type == QV4::CompiledData::Binding::Type_String;
@@ -800,7 +784,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
&& !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
&& !_valueTypeProperty)
- removeBindingOnProperty(_bindingTarget, property->coreIndex);
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, property->coreIndex);
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
@@ -828,18 +812,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (_valueTypeProperty)
targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
- sharedState->allCreatedBindings.push(qmlBinding);
- qmlBinding->m_mePtr = &sharedState->allCreatedBindings.top();
+ sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
- qmlBinding->setTarget(_bindingTarget, targetCorePropertyData, context);
+ qmlBinding->setTarget(_bindingTarget, targetCorePropertyData);
if (targetCorePropertyData.isAlias()) {
- QQmlAbstractBinding *old =
- QQmlPropertyPrivate::setBindingNoEnable(_bindingTarget,
- targetCorePropertyData.coreIndex,
- targetCorePropertyData.getValueTypeCoreIndex(),
- qmlBinding);
- if (old) { old->destroy(); }
+ QQmlPropertyPrivate::setBinding(qmlBinding, QQmlPropertyPrivate::DontEnable);
} else {
qmlBinding->addToObject();
@@ -1011,7 +989,7 @@ QV4::Heap::ExecutionContext *QQmlObjectCreator::currentQmlContext()
{
if (!_qmlBindingWrapper->objectValue()) {
QV4::Scope valueScope(v4);
- QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
+ QV4::Scoped<QV4::QmlContextWrapper> qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
QV4::ScopedContext global(valueScope, v4->rootContext());
*_qmlBindingWrapper = v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope);
}
@@ -1124,7 +1102,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QBitArray bindingsToSkip;
if (customParser) {
- QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.find(index);
+ QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index);
if (customParserBindings != compiledData->customParserBindings.constEnd()) {
customParser->imports = compiledData->importCache;
@@ -1183,13 +1161,14 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
while (!sharedState->allCreatedBindings.isEmpty()) {
- QQmlAbstractBinding *b = sharedState->allCreatedBindings.pop();
- if (!b)
+ QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.pop();
+ Q_ASSERT(b);
+ // skip, if b is not added to an object
+ if (!b->isAddedToObject())
continue;
- b->m_mePtr = 0;
- QQmlData *data = QQmlData::get(b->object());
+ QQmlData *data = QQmlData::get(b->targetObject());
Q_ASSERT(data);
- data->clearPendingBindingBit(b->propertyIndex());
+ data->clearPendingBindingBit(b->targetPropertyIndex());
b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
@@ -1299,7 +1278,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
QBitArray bindingSkipList = bindingsToSkip;
{
- QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(_compiledObjectIndex);
+ QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.constFind(_compiledObjectIndex);
if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
if (bindingSkipList.isEmpty())
bindingSkipList.resize(deferredBindings->count());
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 60fefe494f..c88c15b525 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -55,7 +55,7 @@ struct QQmlObjectCreatorSharedState : public QSharedData
{
QQmlContextData *rootContext;
QQmlContextData *creationContext;
- QFiniteStack<QQmlAbstractBinding*> allCreatedBindings;
+ QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
QFiniteStack<QPointer<QObject> > allCreatedObjects;
QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index fc24b15fd2..c6d2d44ee1 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -277,8 +277,8 @@ void QQmlOpenMetaObject::setValue(int id, const QVariant &value)
QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
- if (iter == d->type->d->names.end())
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
+ if (iter == d->type->d->names.cend())
return QVariant();
return d->getData(*iter);
@@ -286,8 +286,8 @@ QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
QVariant &QQmlOpenMetaObject::operator[](const QByteArray &name)
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
- Q_ASSERT(iter != d->type->d->names.end());
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
+ Q_ASSERT(iter != d->type->d->names.cend());
return d->getData(*iter);
}
@@ -299,10 +299,10 @@ QVariant &QQmlOpenMetaObject::operator[](int id)
bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
int id = -1;
- if (iter == d->type->d->names.end()) {
+ if (iter == d->type->d->names.cend()) {
id = createProperty(name.constData(), "") - d->type->d->propertyOffset;
} else {
id = *iter;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index ae452b727e..414bf8fe0f 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -55,6 +55,7 @@
#include <private/qmetaobject_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <QtCore/qdebug.h>
+#include <cmath>
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QList<qreal>)
@@ -699,8 +700,7 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return 0;
- return binding(that.d->object, that.d->core.coreIndex,
- that.d->core.getValueTypeCoreIndex());
+ return binding(that.d->object, that.d->core.encodedIndex());
}
/*!
@@ -716,65 +716,96 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
\a flags is passed through to the binding and is used for the initial update (when
the binding sets the initial value, it will use these flags for the write).
*/
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBinding(const QQmlProperty &that,
- QQmlAbstractBinding *newBinding,
- WriteFlags flags)
+void
+QQmlPropertyPrivate::setBinding(const QQmlProperty &that, QQmlAbstractBinding *newBinding)
{
+ if (!newBinding) {
+ removeBinding(that);
+ return;
+ }
+
if (!that.d || !that.isProperty() || !that.d->object) {
- if (newBinding)
- newBinding->destroy();
- return 0;
+ if (!newBinding->ref)
+ delete newBinding;
+ return;
}
+ setBinding(newBinding);
+}
+
+static void removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None)
+{
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
- if (newBinding) {
- // In the case that the new binding is provided, we must target the property it
- // is associated with. If we don't do this, retargetBinding() can fail.
- QObject *object = newBinding->object();
- int pi = newBinding->propertyIndex();
+ QQmlData *data = QQmlData::get(object, false);
- int core;
- int vt = QQmlPropertyData::decodeValueTypePropertyIndex(pi, &core);
+ if (!data || !data->hasBindingBit(coreIndex))
+ return;
- return setBinding(object, core, vt, newBinding, flags);
- } else {
- return setBinding(that.d->object, that.d->core.coreIndex,
- that.d->core.getValueTypeCoreIndex(),
- newBinding, flags);
- }
+ QQmlAbstractBinding::Ptr oldBinding;
+ oldBinding = data->bindings;
+
+ while (oldBinding && oldBinding->targetPropertyIndex() != coreIndex)
+ oldBinding = oldBinding->nextBinding();
+
+ if (!oldBinding)
+ return;
+
+ if (valueTypeIndex != -1 && oldBinding->isValueTypeProxy())
+ oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
+
+ if (!oldBinding)
+ return;
+
+ if (!(flags & QQmlPropertyPrivate::DontEnable))
+ oldBinding->setEnabled(false, 0);
+ oldBinding->removeFromObject();
+}
+
+void QQmlPropertyPrivate::removeBinding(QQmlAbstractBinding *b)
+{
+ removeBinding(b->targetObject(), b->targetPropertyIndex());
+}
+
+void QQmlPropertyPrivate::removeBinding(QObject *o, int index)
+{
+ Q_ASSERT(o);
+
+ QObject *target;
+ int targetIndex;
+ findAliasTarget(o, index, &target, &targetIndex);
+ removeOldBinding(target, targetIndex);
+}
+
+void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that)
+{
+ if (!that.d || !that.isProperty() || !that.d->object)
+ return;
+
+ removeBinding(that.d->object, that.d->core.encodedIndex());
}
QQmlAbstractBinding *
-QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
+QQmlPropertyPrivate::binding(QObject *object, int index)
{
QQmlData *data = QQmlData::get(object);
if (!data)
return 0;
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+ findAliasTarget(object, index, &object, &index);
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1)
- return 0;
-
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return binding(aObject, aCoreIndex, aValueTypeIndex);
- }
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
if (!data->hasBindingBit(coreIndex))
return 0;
QQmlAbstractBinding *binding = data->bindings;
- while (binding && binding->propertyIndex() != coreIndex)
+ while (binding && binding->targetPropertyIndex() != coreIndex)
binding = binding->nextBinding();
if (binding && valueTypeIndex != -1) {
- if (binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) {
+ if (binding->isValueTypeProxy()) {
int index = QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeIndex);
binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
}
@@ -786,11 +817,11 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
QObject **targetObject, int *targetBindingIndex)
{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
-
QQmlData *data = QQmlData::get(object, false);
if (data) {
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
+
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
if (propertyData && propertyData->isAlias()) {
@@ -817,119 +848,30 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
*targetBindingIndex = bindingIndex;
}
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeIndex,
- QQmlAbstractBinding *newBinding, WriteFlags flags)
-{
- QQmlData *data = QQmlData::get(object, 0 != newBinding);
- QQmlAbstractBinding *binding = 0;
-
- if (data) {
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
-
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
- if (newBinding) newBinding->destroy();
- return 0;
- }
-
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return setBinding(aObject, aCoreIndex, aValueTypeIndex, newBinding, flags);
- }
- }
-
- if (data && data->hasBindingBit(coreIndex)) {
- binding = data->bindings;
-
- while (binding && binding->propertyIndex() != coreIndex)
- binding = binding->nextBinding();
- }
-
- int index = coreIndex;
- if (valueTypeIndex != -1)
- index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
-
- if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
- binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
-
- if (binding) {
- binding->removeFromObject();
- binding->setEnabled(false, 0);
- }
-
- if (newBinding) {
- if (newBinding->propertyIndex() != index || newBinding->object() != object)
- newBinding->retargetBinding(object, index);
-
- Q_ASSERT(newBinding->propertyIndex() == index);
- Q_ASSERT(newBinding->object() == object);
-
- newBinding->addToObject();
- newBinding->setEnabled(true, flags);
- }
-
- return binding;
-}
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valueTypeIndex,
- QQmlAbstractBinding *newBinding)
+void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, WriteFlags writeFlags)
{
- QQmlData *data = QQmlData::get(object, 0 != newBinding);
- QQmlAbstractBinding *binding = 0;
+ Q_ASSERT(binding);
- if (data) {
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
-
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
- if (newBinding) newBinding->destroy();
- return 0;
- }
+ QObject *object = binding->targetObject();
+ int index = binding->targetPropertyIndex();
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return setBindingNoEnable(aObject, aCoreIndex, aValueTypeIndex, newBinding);
- }
- }
-
- if (data && data->hasBindingBit(coreIndex)) {
- binding = data->bindings;
-
- while (binding && binding->propertyIndex() != coreIndex)
- binding = binding->nextBinding();
+#ifndef QT_NO_DEBUG
+ int coreIndex;
+ QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
+ QQmlData *data = QQmlData::get(object, true);
+ if (data->propertyCache) {
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData && !propertyData->isAlias());
}
+#endif
- int index = coreIndex;
- if (valueTypeIndex != -1)
- index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
-
- if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
- binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
-
- if (binding)
- binding->removeFromObject();
-
- if (newBinding) {
- if (newBinding->propertyIndex() != index || newBinding->object() != object)
- newBinding->retargetBinding(object, index);
-
- Q_ASSERT(newBinding->propertyIndex() == index);
- Q_ASSERT(newBinding->object() == object);
+ removeOldBinding(object, index, flags);
- newBinding->addToObject();
- }
+ binding->addToObject();
+ if (!(flags & DontEnable))
+ binding->setEnabled(true, writeFlags);
- return binding;
}
/*!
@@ -946,9 +888,9 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
if (!data)
return 0;
- QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+ QQmlBoundSignal *signalHandler = data->signalHandlers;
- while (signalHandler && signalHandler->index() != QQmlPropertyPrivate::get(that)->signalIndex())
+ while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
signalHandler = signalHandler->m_nextSignal;
if (signalHandler)
@@ -959,48 +901,41 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
/*!
Set the signal expression associated with this signal property to \a expr.
- Returns the existing signal expression (if any), otherwise null.
-
- A reference to \a expr will be added by QML. Ownership of the return value
- reference is assumed by the caller.
+ A reference to \a expr will be added by QML.
*/
-QQmlBoundSignalExpressionPointer
-QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
- QQmlBoundSignalExpression *expr)
+void QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *expr)
{
if (expr)
expr->addref();
- return QQmlPropertyPrivate::takeSignalExpression(that, expr);
+ QQmlPropertyPrivate::takeSignalExpression(that, expr);
}
/*!
Set the signal expression associated with this signal property to \a expr.
- Returns the existing signal expression (if any), otherwise null.
-
- Ownership of \a expr transfers to QML. Ownership of the return value
- reference is assumed by the caller.
+ Ownership of \a expr transfers to QML.
*/
-QQmlBoundSignalExpressionPointer
-QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
+void QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *expr)
{
if (!(that.type() & QQmlProperty::SignalProperty)) {
if (expr)
expr->release();
- return 0;
+ return;
}
QQmlData *data = QQmlData::get(that.d->object, 0 != expr);
if (!data)
- return 0;
+ return;
- QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+ QQmlBoundSignal *signalHandler = data->signalHandlers;
- while (signalHandler && signalHandler->index() != QQmlPropertyPrivate::get(that)->signalIndex())
+ while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
signalHandler = signalHandler->m_nextSignal;
- if (signalHandler)
- return signalHandler->takeExpression(expr);
+ if (signalHandler) {
+ signalHandler->takeExpression(expr);
+ return;
+ }
if (expr) {
int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
@@ -1008,7 +943,6 @@ QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
expr->context()->engine);
signal->takeExpression(expr);
}
- return 0;
}
/*!
@@ -1125,7 +1059,7 @@ QVariant QQmlPropertyPrivate::readValueProperty()
}
// helper function to allow assignment / binding to QList<QUrl> properties.
-static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
+QVariant QQmlPropertyPrivate::resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
{
QList<QUrl> urls;
if (value.userType() == qMetaTypeId<QUrl>()) {
@@ -1138,16 +1072,22 @@ static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *cont
urls = value.value<QList<QUrl> >();
} else if (value.userType() == qMetaTypeId<QStringList>()) {
QStringList urlStrings = value.value<QStringList>();
- for (int i = 0; i < urlStrings.size(); ++i)
+ const int urlStringsSize = urlStrings.size();
+ urls.reserve(urlStringsSize);
+ for (int i = 0; i < urlStringsSize; ++i)
urls.append(QUrl(urlStrings.at(i)));
} else if (value.userType() == qMetaTypeId<QList<QString> >()) {
QList<QString> urlStrings = value.value<QList<QString> >();
- for (int i = 0; i < urlStrings.size(); ++i)
+ const int urlStringsSize = urlStrings.size();
+ urls.reserve(urlStringsSize);
+ for (int i = 0; i < urlStringsSize; ++i)
urls.append(QUrl(urlStrings.at(i)));
} // note: QList<QByteArray> is not currently supported.
QList<QUrl> resolvedUrls;
- for (int i = 0; i < urls.size(); ++i) {
+ const int urlsSize = urls.size();
+ resolvedUrls.reserve(urlsSize);
+ for (int i = 0; i < urlsSize; ++i) {
QUrl u = urls.at(i);
if (context && u.isRelative() && !u.isEmpty())
u = context->resolvedUrl(u);
@@ -1210,12 +1150,8 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
QQmlContextData *context, WriteFlags flags)
{
// Remove any existing bindings on this property
- if (!(flags & DontRemoveBinding) && object) {
- QQmlAbstractBinding *binding = setBinding(object, core.coreIndex,
- core.getValueTypeCoreIndex(),
- 0, flags);
- if (binding) binding->destroy();
- }
+ if (!(flags & DontRemoveBinding) && object)
+ removeBinding(object, core.encodedIndex());
bool rv = false;
if (core.isValueTypeVirtual()) {
@@ -1255,7 +1191,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
// Enum values come through the script engine as doubles
if (value.userType() == QVariant::Double) {
double integral;
- double fractional = modf(value.toDouble(), &integral);
+ double fractional = std::modf(value.toDouble(), &integral);
if (qFuzzyIsNull(fractional))
v.convert(QVariant::Int);
}
@@ -1475,165 +1411,6 @@ bool QQmlPropertyPrivate::write(QObject *object,
return true;
}
-// Returns true if successful, false if an error description was set on expression
-bool QQmlPropertyPrivate::writeBinding(QObject *object,
- const QQmlPropertyData &core,
- QQmlContextData *context,
- QQmlJavaScriptExpression *expression,
- const QV4::Value &result, bool isUndefined,
- WriteFlags flags)
-{
- Q_ASSERT(object);
- Q_ASSERT(core.coreIndex != -1);
-
- QQmlEngine *engine = context->engine;
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
-
-#define QUICK_STORE(cpptype, conversion) \
- { \
- cpptype o = (conversion); \
- int status = -1; \
- void *argv[] = { &o, 0, &status, &flags }; \
- QMetaObject::metacall(object, QMetaObject::WriteProperty, core.coreIndex, argv); \
- return true; \
- } \
-
-
- if (!isUndefined && !core.isValueTypeVirtual()) {
- switch (core.propType) {
- case QMetaType::Int:
- if (result.isInteger())
- QUICK_STORE(int, result.integerValue())
- else if (result.isNumber())
- QUICK_STORE(int, result.doubleValue())
- break;
- case QMetaType::Double:
- if (result.isNumber())
- QUICK_STORE(double, result.asDouble())
- break;
- case QMetaType::Float:
- if (result.isNumber())
- QUICK_STORE(float, result.asDouble())
- break;
- case QMetaType::QString:
- if (result.isString())
- QUICK_STORE(QString, result.toQStringNoThrow())
- break;
- default:
- if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->typeId == core.propType) {
- return vtw->write(object, core.coreIndex);
- }
- }
- break;
- }
- }
-#undef QUICK_STORE
-
- int type = core.isValueTypeVirtual()?core.valueTypePropType:core.propType;
-
- QQmlJavaScriptExpression::DeleteWatcher watcher(expression);
-
- QVariant value;
- bool isVarProperty = core.isVarProperty();
-
- if (isUndefined) {
- } else if (core.isQList()) {
- value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
- } else if (result.isNull() && core.isQObject()) {
- value = QVariant::fromValue((QObject *)0);
- } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
- value = resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
- } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
- value = QV8Engine::getV4(v8engine)->toVariant(result, type);
- }
-
- if (expression->hasError()) {
- return false;
- } else if (isVarProperty) {
- QV4::FunctionObject *f = result.asFunctionObject();
- if (f && f->isBinding()) {
- // we explicitly disallow this case to avoid confusion. Users can still store one
- // in an array in a var property if they need to, but the common case is user error.
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
-
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
- Q_ASSERT(vmemo);
- vmemo->setVMEProperty(core.coreIndex, result);
- } else if (isUndefined && core.isResettable()) {
- void *args[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::ResetProperty, core.coreIndex, args);
- } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
- writeValueProperty(object, core, QVariant(), context, flags);
- } else if (type == qMetaTypeId<QJSValue>()) {
- QV4::FunctionObject *f = result.asFunctionObject();
- if (f && f->isBinding()) {
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
- writeValueProperty(object, core, QVariant::fromValue(
- QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
- context, flags);
- } else if (isUndefined) {
- QString errorStr = QLatin1String("Unable to assign [undefined] to ");
- if (!QMetaType::typeName(type))
- errorStr += QLatin1String("[unknown property type]");
- else
- errorStr += QLatin1String(QMetaType::typeName(type));
- expression->delayedError()->setErrorDescription(errorStr);
- expression->delayedError()->setErrorObject(object);
- return false;
- } else if (QV4::FunctionObject *f = result.asFunctionObject()) {
- if (f->isBinding())
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- else
- expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
- expression->delayedError()->setErrorObject(object);
- return false;
- } else if (!writeValueProperty(object, core, value, context, flags)) {
-
- if (watcher.wasDeleted())
- return true;
-
- const char *valueType = 0;
- const char *propertyType = 0;
-
- if (value.userType() == QMetaType::QObjectStar) {
- if (QObject *o = *(QObject **)value.constData()) {
- valueType = o->metaObject()->className();
-
- QQmlMetaObject propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
- if (!propertyMetaObject.isNull())
- propertyType = propertyMetaObject.className();
- }
- } else if (value.userType() != QVariant::Invalid) {
- if (value.userType() == QMetaType::VoidStar)
- valueType = "null";
- else
- valueType = QMetaType::typeName(value.userType());
- }
-
- if (!valueType)
- valueType = "undefined";
- if (!propertyType)
- propertyType = QMetaType::typeName(type);
- if (!propertyType)
- propertyType = "[unknown property type]";
-
- expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign ") +
- QLatin1String(valueType) +
- QLatin1String(" to ") +
- QLatin1String(propertyType));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
-
- return true;
-}
QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
{
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 98e310ebce..51a1db7b90 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
class QQmlContext;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
+
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
public:
@@ -103,15 +104,18 @@ public:
QQmlContextData *, WriteFlags flags = 0);
static void findAliasTarget(QObject *, int, QObject **, int *);
- static QQmlAbstractBinding *setBinding(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */,
- QQmlAbstractBinding *,
- WriteFlags flags = DontRemoveBinding);
- static QQmlAbstractBinding *setBindingNoEnable(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */,
- QQmlAbstractBinding *);
- static QQmlAbstractBinding *binding(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */);
+ enum BindingFlag {
+ None = 0,
+ DontEnable = 0x1
+ };
+ Q_DECLARE_FLAGS(BindingFlags, BindingFlag)
+
+ static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, WriteFlags writeFlags = DontRemoveBinding);
+
+ static void removeBinding(const QQmlProperty &that);
+ static void removeBinding(QObject *o, int index);
+ static void removeBinding(QQmlAbstractBinding *b);
+ static QQmlAbstractBinding *binding(QObject *, int index);
static QQmlPropertyData saveValueType(const QQmlPropertyData &,
const QMetaObject *, int,
@@ -128,20 +132,13 @@ public:
// "Public" (to QML) methods
static QQmlAbstractBinding *binding(const QQmlProperty &that);
- static QQmlAbstractBinding *setBinding(const QQmlProperty &that,
- QQmlAbstractBinding *,
- WriteFlags flags = DontRemoveBinding);
+ static void setBinding(const QQmlProperty &that, QQmlAbstractBinding *);
static QQmlBoundSignalExpression *signalExpression(const QQmlProperty &that);
- static QQmlBoundSignalExpressionPointer setSignalExpression(const QQmlProperty &that,
+ static void setSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
- static QQmlBoundSignalExpressionPointer takeSignalExpression(const QQmlProperty &that,
+ static void takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
static bool write(const QQmlProperty &that, const QVariant &, WriteFlags);
- static bool writeBinding(QObject *, const QQmlPropertyData &,
- QQmlContextData *context,
- QQmlJavaScriptExpression *expression,
- const QV4::Value &result, bool isUndefined,
- WriteFlags flags);
static int valueTypeCoreIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlPropertyData &that);
@@ -150,9 +147,12 @@ public:
const QObject *receiver, int method_index,
int type = 0, int *types = 0);
static void flushSignal(const QObject *sender, int signal_index);
+
+ static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::WriteFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::BindingFlags)
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index dd1f93ec00..294f3ccdf9 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -42,7 +42,7 @@
#include <private/qqmlaccessors_p.h>
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <QtCore/qdebug.h>
@@ -837,7 +837,7 @@ void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject)
void QQmlPropertyCache::update(const QMetaObject *metaObject)
{
Q_ASSERT(metaObject);
- Q_ASSERT(stringCache.isEmpty());
+ stringCache.clear();
// Preallocate enough space in the index caches for all the properties/methods/signals that
// are not cached in a parent cache so that the caches never need to be reallocated as this
@@ -862,7 +862,6 @@ void QQmlPropertyCache::update(const QMetaObject *metaObject)
*/
void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
{
- stringCache.clear();
propertyIndexCache.clear();
methodIndexCache.clear();
signalHandlerIndexCache.clear();
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 6ed9ec0d36..4d8c6dd9a5 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -54,7 +54,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
@@ -174,7 +174,6 @@ public:
int propType; // When !NotFullyResolved
const char *propTypeName; // When NotFullyResolved
};
- int coreIndex;
union {
// The notify index is in the range returned by QObjectPrivate::signalIndex().
// This is different from QMetaMethod::methodIndex().
@@ -208,6 +207,7 @@ public:
qintptr accessorData;
};
};
+ int coreIndex;
private:
friend class QQmlPropertyData;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index d713e9ee03..408f17ffde 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -81,7 +81,7 @@
#define ASSERT_MAINTHREAD() do { if (m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in main thread"); } while (false)
#define ASSERT_LOADTHREAD() do { if (!m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in load thread"); } while (false)
-#define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false)
+#define ASSERT_CALLBACK() do { if (!m_typeLoader || !m_typeLoader->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while (false)
#else
@@ -1612,6 +1612,20 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
} else {
QQmlTypeLoader::load(typeData, mode);
}
+ } else if ((mode == PreferSynchronous) && QQmlFile::isSynchronous(url)) {
+ // this was started Asynchronous, but we need to force Synchronous
+ // completion now (if at all possible with this type of URL).
+
+ if (!m_thread->isThisThread()) {
+ // this only works when called directly from the UI thread, but not
+ // when recursively called on the QML thread via resolveTypes()
+
+ while (!typeData->isCompleteOrError()) {
+ unlock();
+ m_thread->waitForNextMessage();
+ lock();
+ }
+ }
}
typeData->addref();
@@ -2114,6 +2128,7 @@ void QQmlTypeData::dataReceived(const Data &data)
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
+ errors.reserve(compiler.errors.count());
foreach (const QQmlJS::DiagnosticMessage &msg, compiler.errors) {
QQmlError e;
e.setUrl(finalUrl());
@@ -2519,8 +2534,8 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
return QV4::PersistentValue();
}
- QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
- QV4::QmlContextWrapper::takeContextOwnership(qmlglobal);
+ QV4::Scoped<QV4::QmlContextWrapper> qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
+ qmlglobal->takeContextOwnership();
m_program->qml.set(scope.engine, qmlglobal);
m_program->run();
@@ -2594,7 +2609,7 @@ void QQmlScriptBlob::dataReceived(const Data &data)
return;
}
if (!unit) {
- unit.take(new EmptyCompilationUnit);
+ unit.adopt(new EmptyCompilationUnit);
}
irUnit.javaScriptCompilationUnit = unit;
irUnit.imports = collector.imports;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index d9ea273698..5be478fa65 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -60,7 +60,7 @@
#include <private/qflagpointer_p.h>
#include <private/qqmlirbuilder_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4script_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index d0658f2c3c..23cc12c895 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -125,7 +125,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, cons
const Import *i = static_cast<const Import *>(importNamespace);
Q_ASSERT(i->scriptIndex == -1);
- QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.find(i);
+ QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.constFind(i);
if (it != m_namespacedImports.constEnd()) {
Result r = query(*it, name);
if (r.isValid())
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 8a2118ef27..1d72b2da0d 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -124,19 +124,19 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
}
-ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlTypeWrapper>());
- QV4::ExecutionEngine *v4 = static_cast<QmlTypeWrapper *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine();
QV4::Scope scope(v4);
- Scoped<QmlTypeWrapper> w(scope, static_cast<QmlTypeWrapper *>(m));
+ Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m));
if (hasProperty)
*hasProperty = true;
- QQmlContextData *context = v4->v8Engine->callingContext();
+ QQmlContextData *context = v4->callingQmlContext();
QObject *object = w->d()->object;
@@ -240,7 +240,7 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
return;
QV4::Scope scope(v4);
- QQmlContextData *context = v4->v8Engine->callingContext();
+ QQmlContextData *context = v4->callingQmlContext();
QQmlType *type = w->d()->type;
if (type && !type->isSingleton() && w->d()->object) {
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 660d2836ff..14741a5bad 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qpointer.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -94,7 +94,7 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object
Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static bool isEqualTo(Managed *that, Managed *o);
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index b147266080..7ebfcd64b7 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -517,7 +517,9 @@ void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant)
if ((variantList.count() % 6) == 0) {
bool allRealsOk = true;
QList<qreal> reals;
- for (int i = 0; i < variantList.count(); i++) {
+ const int variantListCount = variantList.count();
+ reals.reserve(variantListCount);
+ for (int i = 0; i < variantListCount; i++) {
bool ok;
const qreal real = variantList.at(i).toReal(&ok);
reals.append(real);
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 2c02cc0aa1..abd73d7f35 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -209,7 +209,6 @@ struct QQmlEasingValueType
{
QEasingCurve v;
Q_GADGET
- Q_ENUMS(Type)
Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL)
Q_PROPERTY(qreal amplitude READ amplitude WRITE setAmplitude FINAL)
@@ -243,6 +242,7 @@ public:
SineCurve = QEasingCurve::SineCurve, CosineCurve = QEasingCurve::CosineCurve,
Bezier = QEasingCurve::BezierSpline
};
+ Q_ENUM(Type)
Type type() const;
qreal amplitude() const;
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
index cfc9b196d2..3bc8493cbb 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp
+++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
@@ -35,80 +35,42 @@
QT_BEGIN_NAMESPACE
-// Used in qqmlabstractbinding.cpp
-QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable = {
- QQmlAbstractBinding::default_destroy<QQmlValueTypeProxyBinding>,
- QQmlAbstractBinding::default_expression,
- QQmlValueTypeProxyBinding::propertyIndex,
- QQmlValueTypeProxyBinding::object,
- QQmlValueTypeProxyBinding::setEnabled,
- QQmlValueTypeProxyBinding::update,
- QQmlAbstractBinding::default_retargetBinding
-};
-
QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index)
-: QQmlAbstractBinding(ValueTypeProxy), m_object(o), m_index(index), m_bindings(0)
+ : QQmlAbstractBinding(),
+ m_bindings(0)
{
+ m_target = o;
+ m_targetIndex = index;
}
QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding()
{
- QQmlAbstractBinding *binding = m_bindings;
- // This must be identical to the logic in QQmlData::destroyed()
+ QQmlAbstractBinding *binding = m_bindings.data();
while (binding) {
- QQmlAbstractBinding *next = binding->nextBinding();
binding->setAddedToObject(false);
- binding->setNextBinding(0);
- binding->destroy();
- binding = next;
+ binding = binding->nextBinding();
}
}
-void QQmlValueTypeProxyBinding::setEnabled(QQmlAbstractBinding *_This,
- bool e, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
{
- QQmlValueTypeProxyBinding *This = static_cast<QQmlValueTypeProxyBinding *>(_This);
-
- if (e) {
- QQmlAbstractBinding *bindings = This->m_bindings;
- This->recursiveEnable(bindings, flags);
- } else {
- QQmlAbstractBinding *bindings = This->m_bindings;
- This->recursiveDisable(bindings);
+ QQmlAbstractBinding *b = m_bindings.data();
+ while (b) {
+ b->setEnabled(e, flags);
+ b = b->nextBinding();
}
}
-void QQmlValueTypeProxyBinding::recursiveEnable(QQmlAbstractBinding *b, QQmlPropertyPrivate::WriteFlags flags)
-{
- if (!b)
- return;
-
- recursiveEnable(b->nextBinding(), flags);
-
- if (b)
- b->setEnabled(true, flags);
-}
-
-void QQmlValueTypeProxyBinding::recursiveDisable(QQmlAbstractBinding *b)
-{
- if (!b)
- return;
-
- recursiveDisable(b->nextBinding());
-
- if (b)
- b->setEnabled(false, 0);
-}
-
-void QQmlValueTypeProxyBinding::update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags)
+bool QQmlValueTypeProxyBinding::isValueTypeProxy() const
{
+ return true;
}
QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex)
{
- QQmlAbstractBinding *binding = m_bindings;
+ QQmlAbstractBinding *binding = m_bindings.data();
- while (binding && binding->propertyIndex() != propertyIndex)
+ while (binding && binding->targetPropertyIndex() != propertyIndex)
binding = binding->nextBinding();
return binding;
@@ -119,23 +81,20 @@ Removes a collection of bindings, corresponding to the set bits in \a mask.
*/
void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
{
- QQmlAbstractBinding *binding = m_bindings;
+ QQmlAbstractBinding *binding = m_bindings.data();
QQmlAbstractBinding *lastBinding = 0;
while (binding) {
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->propertyIndex());
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->targetPropertyIndex());
if (valueTypeIndex != -1 && (mask & (1 << valueTypeIndex))) {
QQmlAbstractBinding *remove = binding;
+ remove->setAddedToObject(false);
binding = remove->nextBinding();
if (lastBinding == 0)
m_bindings = remove->nextBinding();
else
lastBinding->setNextBinding(remove->nextBinding());
-
- remove->setAddedToObject(false);
- remove->setNextBinding(0);
- remove->destroy();
} else {
lastBinding = binding;
binding = binding->nextBinding();
@@ -143,24 +102,4 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
}
}
-int QQmlValueTypeProxyBinding::propertyIndex(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_index;
-}
-
-QObject *QQmlValueTypeProxyBinding::object(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_object;
-}
-
-int QQmlValueTypeProxyBinding::propertyIndex() const
-{
- return m_index;
-}
-
-QObject *QQmlValueTypeProxyBinding::object() const
-{
- return m_object;
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index 873fbb4af1..4afadfc17d 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -54,30 +54,18 @@ class QQmlValueTypeProxyBinding : public QQmlAbstractBinding
public:
QQmlValueTypeProxyBinding(QObject *o, int coreIndex);
- int propertyIndex() const;
- QObject *object() const;
-
- QQmlAbstractBinding *binding(int propertyIndex);
-
+ QQmlAbstractBinding *binding(int targetPropertyIndex);
void removeBindings(quint32 mask);
- // "Inherited" from QQmlAbstractBinding
- static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- static int propertyIndex(const QQmlAbstractBinding *);
- static QObject *object(const QQmlAbstractBinding *);
+ virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags);
+ virtual bool isValueTypeProxy() const;
protected:
~QQmlValueTypeProxyBinding();
private:
- void recursiveEnable(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- void recursiveDisable(QQmlAbstractBinding *);
-
friend class QQmlAbstractBinding;
- QObject *m_object;
- int m_index;
- QQmlAbstractBinding *m_bindings;
+ Ptr m_bindings;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index e87d9ede77..b0ab85199d 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -43,7 +43,6 @@
#include <private/qv4engine_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4variantobject_p.h>
-#include <private/qv4qmlextensions_p.h>
#include <private/qv4alloca_p.h>
QT_BEGIN_NAMESPACE
@@ -165,13 +164,13 @@ bool QQmlValueTypeReference::readReferenceValue() const
void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4)
{
- if (v4->qmlExtensions()->valueTypeWrapperPrototype)
+ if (v4->valueTypeWrapperPrototype()->as<Object>())
return;
Scope scope(v4);
ScopedObject o(scope, v4->newObject());
- o->defineDefaultProperty(v4->id_toString, method_toString, 1);
- v4->qmlExtensions()->valueTypeWrapperPrototype = o->d();
+ o->defineDefaultProperty(v4->id_toString(), method_toString, 1);
+ v4->jsObjects[QV4::ExecutionEngine::ValueTypeProto] = o->d();
}
ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *object, int property, const QMetaObject *metaObject, int typeId)
@@ -180,7 +179,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
initProto(engine);
Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine));
- ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
+ ScopedObject proto(scope, engine->valueTypeWrapperPrototype());
r->setPrototype(proto);
r->d()->object = object; r->d()->property = property;
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
@@ -195,7 +194,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
initProto(engine);
Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine));
- ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
+ ScopedObject proto(scope, engine->valueTypeWrapperPrototype());
r->setPrototype(proto);
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
@@ -292,7 +291,7 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
{
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QQmlValueTypeWrapper *w = o->as<QQmlValueTypeWrapper>();
@@ -327,14 +326,14 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
return Encode(ctx->engine()->newString(result));
}
-ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
- QQmlValueTypeWrapper *r = static_cast<QQmlValueTypeWrapper *>(m);
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = r->engine();
// Note: readReferenceValue() can change the reference->type.
- if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
+ if (const QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
if (!reference->readReferenceValue())
return Primitive::undefinedValue().asReturnedValue();
}
@@ -410,45 +409,41 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QMetaProperty property = metaObject->property(pd->coreIndex);
Q_ASSERT(property.isValid());
- QQmlBinding *newBinding = 0;
-
- QV4::ScopedFunctionObject f(scope, value);
- if (reference && f) {
- if (!f->isBinding()) {
- // assigning a JS function to a non-var-property is not allowed.
- QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
- ScopedString e(scope, v4->newString(error));
- v4->throwError(e);
- return;
- }
+ if (reference) {
+ QV4::ScopedFunctionObject f(scope, value);
+ if (f) {
+ if (!f->isBinding()) {
+ // assigning a JS function to a non-var-property is not allowed.
+ QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
+ ScopedString e(scope, v4->newString(error));
+ v4->throwError(e);
+ return;
+ }
- QQmlContextData *context = QmlContextWrapper::callingContext(v4);
+ QQmlContextData *context = v4->callingQmlContext();
- QQmlPropertyData cacheData;
- cacheData.setFlags(QQmlPropertyData::IsWritable |
- QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = writeBackPropertyType;
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeFlags = 0;
- cacheData.valueTypeCoreIndex = pd->coreIndex;
- cacheData.valueTypePropType = property.userType();
+ QQmlPropertyData cacheData;
+ cacheData.setFlags(QQmlPropertyData::IsWritable |
+ QQmlPropertyData::IsValueTypeVirtual);
+ cacheData.propType = writeBackPropertyType;
+ cacheData.coreIndex = reference->d()->property;
+ cacheData.valueTypeFlags = 0;
+ cacheData.valueTypeCoreIndex = pd->coreIndex;
+ cacheData.valueTypePropType = property.userType();
- QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
- bindingFunction->initBindingLocation();
+ QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
+ bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData, context);
- }
+ QQmlBinding *newBinding = new QQmlBinding(value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData);
+ QQmlPropertyPrivate::setBinding(newBinding);
+ return;
+ } else {
+ QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyData::encodeValueTypePropertyIndex(reference->d()->property, pd->coreIndex));
- if (reference) {
- QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, pd->coreIndex, newBinding);
- if (oldBinding)
- oldBinding->destroy();
+ }
}
- if (newBinding)
- return;
QVariant v = v4->toVariant(value, property.userType());
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index cad48e661c..5f0edfb71d 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -89,7 +89,7 @@ public:
int typeId() const;
bool write(QObject *target, int propertyIndex) const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
static PropertyAttributes query(const Managed *, String *name);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 5b1be15869..cae4bfa196 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -500,8 +500,8 @@ void QQmlVMEVariant::ensureValueType(int t)
}
QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint)
{
- setCallback(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint);
}
void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
@@ -874,10 +874,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
int flags = *reinterpret_cast<int*>(a[3]);
if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) {
QQmlData *targetData = QQmlData::get(target);
- if (targetData && targetData->hasBindingBit(d->propertyIndex())) {
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(target, d->propertyIndex(), d->isValueTypeAlias()?d->valueTypeIndex():-1, 0);
- if (binding) binding->destroy();
- }
+ if (targetData && targetData->hasBindingBit(d->propertyIndex()))
+ QQmlPropertyPrivate::removeBinding(target, d->propertyIdx);
}
}
@@ -1183,7 +1181,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
v8methods = new QV4::PersistentValue[metaData->methodCount];
int methodIndex = index - methodOffset() - plainSignals;
- v8methods[methodIndex].set(function.asObject()->engine(), function);
+ v8methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
@@ -1220,8 +1218,9 @@ bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
void QQmlVMEMetaObject::ensureQObjectWrapper()
{
- QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
- QV4::ExecutionEngine *v4 = (ep == 0) ? 0 : ep->v4engine();
+ Q_ASSERT(ctxt && ctxt->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(ctxt->engine);
+ QV4::ExecutionEngine *v4 = ep->v4engine();
QV4::QObjectWrapper::wrap(v4, object);
}
@@ -1251,7 +1250,7 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
void QQmlVMEMetaObject::allocateVarPropertiesArray()
{
QQmlEngine *qml = qmlEngine(object);
- assert(qml);
+ Q_ASSERT(qml);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qml->handle());
QV4::Scope scope(v4);
varProperties.set(scope.engine, v4->newArrayObject(metaData->varPropertyCount));
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index d0e2e34ff1..44809a26f0 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -63,7 +63,7 @@
#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 2a3ede6a22..59927fdac7 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -60,6 +60,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4arraybuffer_p.h>
+#include <private/qv4jsonobject_p.h>
using namespace QV4;
@@ -99,7 +100,7 @@ static ReturnedValue constructMeObject(const Value &thisObj, ExecutionEngine *v4
Scope scope(v4);
ScopedObject meObj(scope, v4->newObject());
meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))), thisObj);
- ScopedValue v(scope, QmlContextWrapper::qmlScope(v4, v4->v8Engine->callingContext(), 0));
+ ScopedValue v(scope, QmlContextWrapper::qmlScope(v4, v4->callingQmlContext(), 0));
meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))), v);
return meObj.asReturnedValue();
}
@@ -222,8 +223,8 @@ public:
static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &);
// JS API
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
Heap::NamedNodeMap::NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
@@ -244,8 +245,8 @@ public:
V4_NEEDS_DESTROY
// JS API
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
// C++ API
static ReturnedValue create(ExecutionEngine *, NodeImpl *);
@@ -871,10 +872,10 @@ bool Node::isNull() const
return d()->d == 0;
}
-ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
- NamedNodeMap *r = static_cast<NamedNodeMap *>(m);
+ const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
if ((int)index < r->d()->list.count()) {
@@ -887,14 +888,14 @@ ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty
return Encode::undefined();
}
-ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
- NamedNodeMap *r = static_cast<NamedNodeMap *>(m);
+ const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
name->makeIdentifier(v4);
- if (name->equals(v4->id_length))
+ if (name->equals(v4->id_length()))
return Primitive::fromInt32(r->d()->list.count()).asReturnedValue();
QString str = name->toQString();
@@ -916,10 +917,10 @@ ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QL
return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue();
}
-ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
- NodeList *r = static_cast<NodeList *>(m);
+ const NodeList *r = static_cast<const NodeList *>(m);
QV4::ExecutionEngine *v4 = r->engine();
if ((int)index < r->d()->d->children.count()) {
@@ -932,15 +933,15 @@ ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue NodeList::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
- NodeList *r = static_cast<NodeList *>(m);
+ const NodeList *r = static_cast<const NodeList *>(m);
QV4::ExecutionEngine *v4 = r->engine();
name->makeIdentifier(v4);
- if (name->equals(v4->id_length))
+ if (name->equals(v4->id_length()))
return Primitive::fromInt32(r->d()->d->children.count()).asReturnedValue();
return Object::get(m, name, hasProperty);
}
@@ -1026,6 +1027,8 @@ public:
const QString & responseType() const;
void setResponseType(const QString &);
+
+ QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*);
private slots:
void readyRead();
void error(QNetworkReply::NetworkError);
@@ -1076,6 +1079,7 @@ private:
QNetworkAccessManager *networkAccessManager() { return m_nam; }
QString m_responseType;
+ QV4::PersistentValue m_parsedJson;
};
QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager)
@@ -1083,6 +1087,7 @@ QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessMa
, m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
, m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
, m_responseType()
+ , m_parsedJson()
{
}
@@ -1478,6 +1483,24 @@ void QQmlXMLHttpRequest::setResponseType(const QString &responseType)
m_responseType = responseType;
}
+QV4::ReturnedValue QQmlXMLHttpRequest::jsonResponseBody(QV4::ExecutionEngine* engine)
+{
+ if (m_parsedJson.isEmpty()) {
+ Scope scope(engine);
+
+ QJsonParseError error;
+ const QString& jtext = responseBody();
+ JsonParser parser(scope.engine, jtext.constData(), jtext.length());
+ ScopedValue jsonObject(scope, parser.parse(&error));
+ if (error.error != QJsonParseError::NoError)
+ return engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
+
+ m_parsedJson.set(scope.engine, jsonObject);
+ }
+
+ return m_parsedJson.value();
+}
+
#ifndef QT_NO_TEXTCODEC
QTextCodec* QQmlXMLHttpRequest::findTextCodec() const
@@ -1599,7 +1622,7 @@ struct QQmlXMLHttpRequestWrapper : Object {
struct QQmlXMLHttpRequestCtor : FunctionObject {
QQmlXMLHttpRequestCtor(ExecutionEngine *engine);
- Object *proto;
+ Pointer<Object> proto;
};
}
@@ -1625,9 +1648,9 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
c->proto->mark(e);
FunctionObject::markObjects(that, e);
}
- static ReturnedValue construct(Managed *that, QV4::CallData *)
+ static ReturnedValue construct(const Managed *that, QV4::CallData *)
{
- Scope scope(static_cast<QQmlXMLHttpRequestCtor *>(that)->engine());
+ Scope scope(static_cast<const QQmlXMLHttpRequestCtor *>(that)->engine());
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>());
if (!ctor)
return scope.engine->throwTypeError();
@@ -1639,7 +1662,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
return w.asReturnedValue();
}
- static ReturnedValue call(Managed *, QV4::CallData *) {
+ static ReturnedValue call(const Managed *, QV4::CallData *) {
return Primitive::undefinedValue().asReturnedValue();
}
@@ -1679,7 +1702,7 @@ Heap::QQmlXMLHttpRequestCtor::QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
ctor->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
if (!ctor->d()->proto)
ctor->setupProto();
- ScopedString s(scope, engine->id_prototype);
+ ScopedString s(scope, engine->id_prototype());
ctor->defineDefaultProperty(s, ScopedObject(scope, ctor->d()->proto));
}
@@ -1746,7 +1769,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
QUrl url = QUrl(ctx->args()[1].toQStringNoThrow());
if (url.isRelative())
- url = scope.engine->v8Engine->callingContext()->resolvedUrl(url);
+ url = scope.engine->callingQmlContext()->resolvedUrl(url);
bool async = true;
// Argument 2 - async (optional)
@@ -1986,6 +2009,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx)
return QV4::Encode(scope.engine->newString(r->responseBody()));
} else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) {
return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody()));
+ } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) {
+ return r->jsonResponseBody(scope.engine);
} else {
return QV4::Encode(scope.engine->newString(QString()));
}
@@ -2033,7 +2058,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
- v4->globalObject()->defineReadonlyProperty(s, ctor);
+ v4->globalObject->defineReadonlyProperty(s, ctor);
QQmlXMLHttpRequestData *data = new QQmlXMLHttpRequestData;
return data;
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index f53b9a0c7d..aff6de7f5e 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -51,6 +51,7 @@
#include <private/qv4include_p.h>
#include <private/qv4context_p.h>
#include <private/qv4stringobject_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4mm_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4objectproto_p.h>
@@ -669,7 +670,7 @@ ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx)
QVariant argVariant = ctx->engine()->toVariant(ctx->args()[0], -1);
QTime time;
- if (ctx->args()[0].asDateObject() || (argVariant.type() == QVariant::String))
+ if (ctx->args()[0].as<DateObject>() || (argVariant.type() == QVariant::String))
time = argVariant.toDateTime().time();
else // if (argVariant.type() == QVariant::Time), or invalid.
time = argVariant.toTime();
@@ -839,21 +840,21 @@ ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
*/
ReturnedValue QtObject::method_resolvedUrl(QV4::CallContext *ctx)
{
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ ExecutionEngine *v4 = ctx->engine();
- QUrl url = ctx->engine()->toVariant(ctx->args()[0], -1).toUrl();
- QQmlEngine *e = v8engine->engine();
+ QUrl url = v4->toVariant(ctx->args()[0], -1).toUrl();
+ QQmlEngine *e = v4->qmlEngine();
QQmlEnginePrivate *p = 0;
if (e) p = QQmlEnginePrivate::get(e);
if (p) {
- QQmlContextData *ctxt = v8engine->callingContext();
+ QQmlContextData *ctxt = v4->callingQmlContext();
if (ctxt)
- return ctx->d()->engine->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
+ return v4->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
else
- return ctx->d()->engine->newString(url.toString())->asReturnedValue();
+ return v4->newString(url.toString())->asReturnedValue();
}
- return ctx->d()->engine->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
+ return v4->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
}
/*!
@@ -983,7 +984,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
QQmlContext *effectiveContext = 0;
if (context->isPragmaLibraryContext)
@@ -1090,7 +1091,7 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
QQmlContextData *effectiveContext = context;
if (context->isPragmaLibraryContext)
@@ -1178,7 +1179,7 @@ ReturnedValue QtObject::method_locale(CallContext *ctx)
return QQmlLocale::locale(ctx->engine(), code);
}
-Heap::QQmlBindingFunction::QQmlBindingFunction(QV4::FunctionObject *originalFunction)
+Heap::QQmlBindingFunction::QQmlBindingFunction(const QV4::FunctionObject *originalFunction)
: QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name())
, originalFunction(originalFunction->d())
{
@@ -1191,10 +1192,10 @@ void QQmlBindingFunction::initBindingLocation()
d()->bindingLocation.line = frame.line;
}
-ReturnedValue QQmlBindingFunction::call(Managed *that, CallData *callData)
+ReturnedValue QQmlBindingFunction::call(const Managed *that, CallData *callData)
{
- Scope scope(static_cast<QQmlBindingFunction*>(that)->engine());
- ScopedFunctionObject function(scope, static_cast<QQmlBindingFunction*>(that)->d()->originalFunction);
+ Scope scope(static_cast<const QQmlBindingFunction*>(that)->engine());
+ ScopedFunctionObject function(scope, static_cast<const QQmlBindingFunction*>(that)->d()->originalFunction);
return function->call(callData);
}
@@ -1256,7 +1257,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx)
{
if (ctx->argc() != 1)
V4THROW_ERROR("binding() requires 1 argument");
- QV4::FunctionObject *f = ctx->args()[0].asFunctionObject();
+ const QV4::FunctionObject *f = ctx->args()[0].as<FunctionObject>();
if (!f)
V4THROW_TYPE("binding(): argument (binding expression) must be a function");
@@ -1267,7 +1268,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx)
ReturnedValue QtObject::method_get_platform(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
@@ -1284,7 +1285,7 @@ ReturnedValue QtObject::method_get_platform(CallContext *ctx)
ReturnedValue QtObject::method_get_application(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
@@ -1379,7 +1380,7 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
if (i != 0)
result.append(QLatin1Char(' '));
- if (ctx->args()[i].asArrayObject())
+ if (ctx->args()[i].as<ArrayObject>())
result.append(QStringLiteral("[") + ctx->args()[i].toQStringNoThrow() + QStringLiteral("]"));
else
result.append(ctx->args()[i].toQStringNoThrow());
@@ -1612,7 +1613,7 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
// string prototype extension
- v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
+ v4->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
}
@@ -1726,9 +1727,8 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
V4THROW_ERROR("qsTr(): third argument (n) must be a number");
Scope scope(ctx);
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QString context;
- if (QQmlContextData *ctxt = v8engine->callingContext()) {
+ if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
QString path = ctxt->urlString();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
int lastDot = path.lastIndexOf(QLatin1Char('.'));
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index b78375118b..bdd53fe601 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -68,8 +68,8 @@ struct ConsoleObject : Object {
};
struct QQmlBindingFunction : FunctionObject {
- QQmlBindingFunction(QV4::FunctionObject *originalFunction);
- FunctionObject *originalFunction;
+ QQmlBindingFunction(const QV4::FunctionObject *originalFunction);
+ Pointer<FunctionObject> originalFunction;
// Set when the binding is created later
QQmlSourceLocation bindingLocation;
};
@@ -166,7 +166,7 @@ struct QQmlBindingFunction : public QV4::FunctionObject
void initBindingLocation(); // from caller stack trace
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/qml/v8/qv4domerrors.cpp b/src/qml/qml/v8/qv4domerrors.cpp
index c318e2e550..1baaa113aa 100644
--- a/src/qml/qml/v8/qv4domerrors.cpp
+++ b/src/qml/qml/v8/qv4domerrors.cpp
@@ -59,7 +59,7 @@ void qt_add_domexceptions(ExecutionEngine *e)
domexception->defineReadonlyProperty(QStringLiteral("INVALID_ACCESS_ERR"), Primitive::fromInt32(DOMEXCEPTION_INVALID_ACCESS_ERR));
domexception->defineReadonlyProperty(QStringLiteral("VALIDATION_ERR"), Primitive::fromInt32(DOMEXCEPTION_VALIDATION_ERR));
domexception->defineReadonlyProperty(QStringLiteral("TYPE_MISMATCH_ERR"), Primitive::fromInt32(DOMEXCEPTION_TYPE_MISMATCH_ERR));
- e->globalObject()->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
+ e->globalObject->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv4sqlerrors.cpp b/src/qml/qml/v8/qv4sqlerrors.cpp
index b7a5b71540..c61e57560d 100644
--- a/src/qml/qml/v8/qv4sqlerrors.cpp
+++ b/src/qml/qml/v8/qv4sqlerrors.cpp
@@ -51,7 +51,7 @@ void qt_add_sqlexceptions(QV4::ExecutionEngine *engine)
sqlexception->defineReadonlyProperty(QStringLiteral("SYNTAX_ERR"), Primitive::fromInt32(SQLEXCEPTION_SYNTAX_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("CONSTRAINT_ERR"), Primitive::fromInt32(SQLEXCEPTION_CONSTRAINT_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("TIMEOUT_ERR"), Primitive::fromInt32(SQLEXCEPTION_TIMEOUT_ERR));
- engine->globalObject()->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
+ engine->globalObject->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index a7c63c9df1..6cb316ce9f 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -61,7 +61,7 @@
#include <QtCore/qdatastream.h>
#include <private/qsimd_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4mm_p.h>
@@ -171,15 +171,10 @@ const QSet<QString> &QV8Engine::illegalNames() const
return m_illegalNames;
}
-QQmlContextData *QV8Engine::callingContext()
-{
- return QV4::QmlContextWrapper::callingContext(m_v4Engine);
-}
-
void QV8Engine::initializeGlobal()
{
QV4::Scope scope(m_v4Engine);
- QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject());
+ QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject);
QQmlLocale::registerStringLocaleCompare(m_v4Engine);
QQmlDateExtension::registerExtension(m_v4Engine);
@@ -191,9 +186,9 @@ void QV8Engine::initializeGlobal()
qt_add_sqlexceptions(m_v4Engine);
{
- for (uint i = 0; i < m_v4Engine->globalObject()->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject()->internalClass()->nameMap.at(i))
- m_illegalNames.insert(m_v4Engine->globalObject()->internalClass()->nameMap.at(i)->string);
+ for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
+ if (m_v4Engine->globalObject->internalClass()->nameMap.at(i))
+ m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string);
}
}
@@ -229,7 +224,7 @@ void QV8Engine::freezeObject(const QV4::Value &value)
QV4::ScopedFunctionObject f(scope, m_freezeObject.value());
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = value;
- callData->thisObject = m_v4Engine->globalObject();
+ callData->thisObject = m_v4Engine->globalObject;
f->call(callData);
}
@@ -266,9 +261,7 @@ void QV8Engine::setExtensionData(int index, Deletable *data)
void QV8Engine::initQmlGlobalObject()
{
initializeGlobal();
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedValue v(scope, m_v4Engine->globalObject());
- freezeObject(v);
+ freezeObject(*m_v4Engine->globalObject);
}
void QV8Engine::setEngine(QQmlEngine *engine)
@@ -279,7 +272,7 @@ void QV8Engine::setEngine(QQmlEngine *engine)
QV4::ReturnedValue QV8Engine::global()
{
- return m_v4Engine->globalObject()->asReturnedValue();
+ return m_v4Engine->globalObject->asReturnedValue();
}
void QV8Engine::startTimer(const QString &timerName)
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index fb538772d1..55e4b15b77 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -60,7 +60,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qv4qobjectwrapper_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
#include <private/qv4identifier_p.h>
@@ -101,19 +101,19 @@ namespace QV4 {
return rv; \
} \
-// Used to allow a QObject method take and return raw V8 handles without having to expose
-// v8 in the public API.
+// Used to allow a QObject method take and return raw V4 handles without having to expose
+// 48 in the public API.
// Use like this:
// class MyClass : public QObject {
// Q_OBJECT
// ...
-// Q_INVOKABLE void myMethod(QQmlV8Function*);
+// Q_INVOKABLE void myMethod(QQmlV4Function*);
// };
// The QQmlV8Function - and consequently the arguments and return value - only remains
// valid during the call. If the return value isn't set within myMethod(), the will return
// undefined.
class QV8Engine;
-// ### GC
+
class QQmlV4Function
{
public:
@@ -163,8 +163,6 @@ class QQmlContextData;
class Q_QML_PRIVATE_EXPORT QV8Engine
{
friend class QJSEngine;
- // ### GC
- typedef QSet<QV4::Heap::Object *> V8ObjectSet;
public:
static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
@@ -192,8 +190,6 @@ public:
Deletable *listModelData() { return m_listModelData; }
void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
- QQmlContextData *callingContext();
-
void freezeObject(const QV4::Value &value);
// Return the network access manager for this engine. By default this returns the network
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 7814fa6d56..8b94769772 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -52,8 +52,8 @@ QT_BEGIN_NAMESPACE
class QQmlBindPrivate : public QObjectPrivate
{
public:
- QQmlBindPrivate() : componentComplete(true), obj(0), prevBind(0) {}
- ~QQmlBindPrivate() { if (prevBind) prevBind->destroy(); }
+ QQmlBindPrivate() : componentComplete(true), obj(0) {}
+ ~QQmlBindPrivate() { }
QQmlNullableValue<bool> when;
bool componentComplete;
@@ -61,7 +61,7 @@ public:
QString propName;
QQmlNullableValue<QVariant> value;
QQmlProperty prop;
- QQmlAbstractBinding *prevBind;
+ QQmlAbstractBinding::Ptr prevBind;
};
@@ -277,22 +277,17 @@ void QQmlBind::eval()
if (!d->when) {
//restore any previous binding
if (d->prevBind) {
- QQmlAbstractBinding *tmp = d->prevBind;
+ QQmlAbstractBinding::Ptr p = d->prevBind;
d->prevBind = 0;
- tmp = QQmlPropertyPrivate::setBinding(d->prop, tmp);
- if (tmp) //should this ever be true?
- tmp->destroy();
+ QQmlPropertyPrivate::setBinding(p.data());
}
return;
}
//save any set binding for restoration
- QQmlAbstractBinding *tmp;
- tmp = QQmlPropertyPrivate::setBinding(d->prop, 0);
- if (tmp && d->prevBind)
- tmp->destroy();
- else if (!d->prevBind)
- d->prevBind = tmp;
+ if (!d->prevBind)
+ d->prevBind = QQmlPropertyPrivate::binding(d->prop);
+ QQmlPropertyPrivate::removeBinding(d->prop);
}
d->prop.write(d->value.value);
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 0c81855e49..6a93410ecb 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -165,7 +165,7 @@ void QQmlConnections::setTarget(QObject *obj)
foreach (QQmlBoundSignal *s, d->boundsignals) {
// It is possible that target is being changed due to one of our signal
// handlers -> use deleteLater().
- if (s->isEvaluating())
+ if (s->isNotifying())
(new QQmlBoundSignalDeleter(s))->deleteLater();
else
delete s;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 201fd4572c..630c7e7e4a 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -44,7 +44,7 @@
#include <private/qqmlincubator_p.h>
#include <private/qqmlcompiler_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <qv4objectiterator_p.h>
@@ -86,16 +86,11 @@ struct DelegateModelGroupFunction : QV4::FunctionObject
return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
}
- static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *)
+ static QV4::ReturnedValue call(const QV4::Managed *that, QV4::CallData *callData)
{
- return static_cast<DelegateModelGroupFunction *>(m)->engine()->throwTypeError();
- }
-
- static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData)
- {
- QV4::ExecutionEngine *v4 = static_cast<DelegateModelGroupFunction *>(that)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const DelegateModelGroupFunction *>(that)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<DelegateModelGroupFunction *>(that));
+ QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<const DelegateModelGroupFunction *>(that));
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject);
if (!o)
return v4->throwTypeError(QStringLiteral("Not a valid VisualData object"));
@@ -1637,7 +1632,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
if (!object.isObject())
return false;
- QV4::ExecutionEngine *v4 = object.asObject()->engine();
+ QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, object);
if (!o)
@@ -2511,7 +2506,7 @@ bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *ind
if (!value.isObject())
return false;
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
@@ -2579,9 +2574,9 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args)
groups |= model->m_cacheMetaType->parseGroups(val);
}
- if (v->asArrayObject()) {
+ if (v->as<QV4::ArrayObject>()) {
return;
- } else if (v->asObject()) {
+ } else if (v->as<QV4::Object>()) {
model->insert(before, v, groups);
model->emitChanges();
}
@@ -2626,7 +2621,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args)
if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
v = (*args)[i];
- if (v->asObject()) {
+ if (v->as<QV4::Object>()) {
int groups = 1 << d->group;
if (++i < args->length()) {
QV4::ScopedValue val(scope, (*args)[i]);
@@ -3286,12 +3281,12 @@ public:
quint32 count() const { return d()->changes.count(); }
const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); }
- static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty)
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QV4::ExecutionEngine *v4 = static_cast<QQmlDelegateModelGroupChangeArray *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<QQmlDelegateModelGroupChangeArray *>(m));
+ QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m));
if (index >= array->count()) {
if (hasProperty)
@@ -3311,12 +3306,12 @@ public:
return object.asReturnedValue();
}
- static QV4::ReturnedValue get(QV4::Managed *m, QV4::String *name, bool *hasProperty)
+ static QV4::ReturnedValue get(const QV4::Managed *m, QV4::String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QQmlDelegateModelGroupChangeArray *array = static_cast<QQmlDelegateModelGroupChangeArray *>(m);
+ const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m);
- if (name->equals(array->engine()->id_length)) {
+ if (name->equals(array->engine()->id_length())) {
if (hasProperty)
*hasProperty = true;
return QV4::Encode(array->count());
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index ed97690adb..6fc0e4a9d8 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -150,7 +150,9 @@ const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::R
ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockOffset(0)
{
- for (int i=0 ; i < other->roles.count() ; ++i) {
+ const int otherRolesCount = other->roles.count();
+ roles.reserve(otherRolesCount);
+ for (int i=0 ; i < otherRolesCount; ++i) {
Role *role = new Role(other->roles[i]);
roles.append(role);
roleHash.insert(role->name, role);
@@ -421,13 +423,13 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
int roleIndex = -1;
// Add the value now
- if (QV4::String *s = propertyValue->asString()) {
+ if (const QV4::String *s = propertyValue->as<QV4::String>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
roleIndex = e->setStringProperty(r, s->toQString());
} else if (propertyValue->isNumber()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
- } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
+ } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
@@ -441,11 +443,11 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
} else if (propertyValue->isBoolean()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
- } else if (QV4::DateObject *dd = propertyValue->asDateObject()) {
+ } else if (QV4::DateObject *dd = propertyValue->as<QV4::DateObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
QDateTime dt = dd->toQDateTime();
roleIndex = e->setDateTimeProperty(r, dt);
- } else if (QV4::Object *o = propertyValue->asObject()) {
+ } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
@@ -502,7 +504,7 @@ void ListModel::set(int elementIndex, QV4::Object *object)
if (r.type == ListLayout::Role::Number) {
e->setDoublePropertyFast(r, propertyValue->asDouble());
}
- } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
+ } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
if (r.type == ListLayout::Role::List) {
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
@@ -520,13 +522,13 @@ void ListModel::set(int elementIndex, QV4::Object *object)
if (r.type == ListLayout::Role::Bool) {
e->setBoolPropertyFast(r, propertyValue->booleanValue());
}
- } else if (QV4::DateObject *date = propertyValue->asDateObject()) {
+ } 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();;
e->setDateTimePropertyFast(r, dt);
}
- } else if (QV4::Object *o = propertyValue->asObject()) {
+ } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
@@ -1169,7 +1171,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
roleIndex = setStringProperty(role, qstr);
} else if (d.isNumber()) {
roleIndex = setDoubleProperty(role, d.asDouble());
- } else if (d.asArrayObject()) {
+ } else if (d.as<QV4::ArrayObject>()) {
QV4::ScopedArrayObject a(scope, d);
if (role.type == ListLayout::Role::List) {
QV4::Scope scope(a->engine());
@@ -1187,7 +1189,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
}
} else if (d.isBoolean()) {
roleIndex = setBoolProperty(role, d.booleanValue());
- } else if (d.asDateObject()) {
+ } else if (d.as<QV4::DateObject>()) {
QV4::Scoped<QV4::DateObject> dd(scope, d);
QDateTime dt = dd->toQDateTime();
roleIndex = setDateTimeProperty(role, dt);
@@ -1330,8 +1332,8 @@ void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int>
QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);
QVariantList subArray = value.toList();
- QVariantList::const_iterator subIt = subArray.begin();
- QVariantList::const_iterator subEnd = subArray.end();
+ QVariantList::const_iterator subIt = subArray.cbegin();
+ QVariantList::const_iterator subEnd = subArray.cend();
while (subIt != subEnd) {
const QVariantMap &subObject = subIt->toMap();
subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
@@ -1398,8 +1400,8 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);
QVariantList subArray = v.toList();
- QVariantList::const_iterator subIt = subArray.begin();
- QVariantList::const_iterator subEnd = subArray.end();
+ QVariantList::const_iterator subIt = subArray.cbegin();
+ QVariantList::const_iterator subEnd = subArray.cend();
while (subIt != subEnd) {
const QVariantMap &subObject = subIt->toMap();
subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
index 3e53efd8b9..062d30c252 100644
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ b/src/qml/types/qqmlmodelsmodule.cpp
@@ -48,6 +48,7 @@ void QQmlModelsModule::defineModule()
qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
+ qmlRegisterType<QQmlObjectModel,3>(uri, 2, 3, "ObjectModel");
qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
}
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
index 1d892beabf..0076c26950 100644
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ b/src/qml/types/qqmlobjectmodel.cpp
@@ -36,10 +36,12 @@
#include <QtCore/qcoreapplication.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlinfo.h>
#include <private/qqmlchangeset_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qobject_p.h>
+#include <private/qpodvector_p.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
@@ -67,9 +69,8 @@ public:
QQmlObjectModelPrivate() : QObjectPrivate() {}
static void children_append(QQmlListProperty<QObject> *prop, QObject *item) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->children.append(Item(item));
- static_cast<QQmlObjectModelPrivate *>(prop->data)->itemAppended();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->emitChildrenChanged();
+ int index = static_cast<QQmlObjectModelPrivate *>(prop->data)->children.count();
+ static_cast<QQmlObjectModelPrivate *>(prop->data)->insert(index, item);
}
static int children_count(QQmlListProperty<QObject> *prop) {
@@ -81,33 +82,77 @@ public:
}
static void children_clear(QQmlListProperty<QObject> *prop) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->itemCleared(static_cast<QQmlObjectModelPrivate *>(prop->data)->children);
- static_cast<QQmlObjectModelPrivate *>(prop->data)->children.clear();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->emitChildrenChanged();
+ static_cast<QQmlObjectModelPrivate *>(prop->data)->clear();
}
- void itemAppended() {
+ void insert(int index, QObject *item) {
Q_Q(QQmlObjectModel);
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.last().item);
- attached->setIndex(children.count()-1);
+ children.insert(index, Item(item));
+ for (int i = index; i < children.count(); ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(i);
+ }
QQmlChangeSet changeSet;
- changeSet.insert(children.count() - 1, 1);
+ changeSet.insert(index, 1);
emit q->modelUpdated(changeSet, false);
emit q->countChanged();
+ emit q->childrenChanged();
}
- void itemCleared(const QList<Item> &children) {
+ void move(int from, int to, int n) {
Q_Q(QQmlObjectModel);
- foreach (const Item &child, children)
- emit q->destroyingItem(child.item);
- emit q->countChanged();
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+
+ QPODVector<QQmlObjectModelPrivate::Item, 4> store;
+ for (int i = 0; i < to - from; ++i)
+ store.append(children[from + n + i]);
+ for (int i = 0; i < n; ++i)
+ store.append(children[from + i]);
+
+ for (int i = 0; i < store.count(); ++i) {
+ children[from + i] = store[i];
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(from + i).item);
+ attached->setIndex(from + i);
+ }
+
+ QQmlChangeSet changeSet;
+ changeSet.move(from, to, n, -1);
+ emit q->modelUpdated(changeSet, false);
+ emit q->childrenChanged();
}
- void emitChildrenChanged() {
+ void remove(int index, int n) {
Q_Q(QQmlObjectModel);
+ for (int i = index; i < index + n; ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(-1);
+ }
+ children.erase(children.begin() + index, children.begin() + index + n);
+ for (int i = index; i < children.count(); ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(i);
+ }
+ QQmlChangeSet changeSet;
+ changeSet.remove(index, n);
+ emit q->modelUpdated(changeSet, false);
+ emit q->countChanged();
emit q->childrenChanged();
}
+ void clear() {
+ Q_Q(QQmlObjectModel);
+ foreach (const Item &child, children)
+ emit q->destroyingItem(child.item);
+ remove(0, children.count());
+ }
+
int indexOf(QObject *item) const {
for (int i = 0; i < children.count(); ++i)
if (children.at(i).item == item)
@@ -258,4 +303,133 @@ QQmlObjectModelAttached *QQmlObjectModel::qmlAttachedProperties(QObject *obj)
return QQmlObjectModelAttached::properties(obj);
}
+/*!
+ \qmlmethod object QtQml.Models::ObjectModel::get(int index)
+ \since 5.6
+
+ Returns the item at \a index in the model. This allows the item
+ to be accessed or modified from JavaScript:
+
+ \code
+ Component.onCompleted: {
+ objectModel.append(objectComponent.createObject())
+ console.log(objectModel.get(0).objectName);
+ objectModel.get(0).objectName = "first";
+ }
+ \endcode
+
+ The \a index must be an element in the list.
+
+ \sa append()
+*/
+QObject *QQmlObjectModel::get(int index) const
+{
+ Q_D(const QQmlObjectModel);
+ if (index < 0 || index >= d->children.count())
+ return 0;
+ return d->children.at(index).item;
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::append(object item)
+ \since 5.6
+
+ Appends a new item to the end of the model.
+
+ \code
+ objectModel.append(objectComponent.createObject())
+ \endcode
+
+ \sa insert(), remove()
+*/
+void QQmlObjectModel::append(QObject *object)
+{
+ Q_D(QQmlObjectModel);
+ d->insert(count(), object);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::insert(int index, object item)
+ \since 5.6
+
+ Inserts a new item to the model at position \a index.
+
+ \code
+ objectModel.insert(2, objectComponent.createObject())
+ \endcode
+
+ The \a index must be to an existing item in the list, or one past
+ the end of the list (equivalent to append).
+
+ \sa append(), remove()
+*/
+void QQmlObjectModel::insert(int index, QObject *object)
+{
+ Q_D(QQmlObjectModel);
+ if (index < 0 || index > count()) {
+ qmlInfo(this) << tr("insert: index %1 out of range").arg(index);
+ return;
+ }
+ d->insert(index, 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.
+
+ The from and to ranges must exist; for example, to move the first 3 items
+ to the end of the model:
+
+ \code
+ objectModel.move(0, objectModel.count - 3, 3)
+ \endcode
+
+ \sa append()
+*/
+void QQmlObjectModel::move(int from, int to, int n)
+{
+ Q_D(QQmlObjectModel);
+ if (n <= 0 || from == to)
+ return;
+ if (from < 0 || to < 0 || from + n > count() || to + n > count()) {
+ qmlInfo(this) << tr("move: out of range");
+ return;
+ }
+ d->move(from, to, n);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::remove(int index, int n = 1)
+ \since 5.6
+
+ Removes the items at \a index from the model.
+
+ \sa clear()
+*/
+void QQmlObjectModel::remove(int index, int n)
+{
+ Q_D(QQmlObjectModel);
+ if (index < 0 || n <= 0 || index + n > count()) {
+ qmlInfo(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
+ return;
+ }
+ d->remove(index, n);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::clear()
+ \since 5.6
+
+ Clears all items from the model.
+
+ \sa append(), remove()
+*/
+void QQmlObjectModel::clear()
+{
+ Q_D(QQmlObjectModel);
+ d->clear();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmlobjectmodel_p.h b/src/qml/types/qqmlobjectmodel_p.h
index 4c37a5ac30..9f56ad7121 100644
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ b/src/qml/types/qqmlobjectmodel_p.h
@@ -107,6 +107,15 @@ public:
static QQmlObjectModelAttached *qmlAttachedProperties(QObject *obj);
+ Q_REVISION(3) Q_INVOKABLE QObject *get(int index) const;
+ Q_REVISION(3) Q_INVOKABLE void append(QObject *object);
+ Q_REVISION(3) Q_INVOKABLE void insert(int index, QObject *object);
+ Q_REVISION(3) Q_INVOKABLE void move(int from, int to, int n = 1);
+ Q_REVISION(3) Q_INVOKABLE void remove(int index, int n = 1);
+
+public Q_SLOTS:
+ Q_REVISION(3) void clear();
+
Q_SIGNALS:
void childrenChanged();
@@ -120,7 +129,7 @@ class QQmlObjectModelAttached : public QObject
public:
QQmlObjectModelAttached(QObject *parent)
- : QObject(parent), m_index(0) {}
+ : QObject(parent), m_index(-1) {}
~QQmlObjectModelAttached() {
attachedProperties.remove(parent());
}
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index c2c6e5ef5c..0aa5dc4ef6 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -54,7 +54,7 @@
#include <private/qv8engine_p.h>
#include <private/qv4serialize_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 356970eef0..17f4ffd62b 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -38,7 +38,7 @@
#include <private/qqmlproperty_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -159,7 +159,9 @@ public:
signalIndexes.append(propertyId + signalOffset);
}
if (roles.isEmpty()) {
- for (int propertyId = 0; propertyId < propertyRoles.count(); ++propertyId)
+ const int propertyRolesCount = propertyRoles.count();
+ signalIndexes.reserve(propertyRolesCount);
+ for (int propertyId = 0; propertyId < propertyRolesCount; ++propertyId)
signalIndexes.append(propertyId + signalOffset);
}
diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro
index df1b750282..85f21ce6f6 100644
--- a/src/qmldevtools/qmldevtools.pro
+++ b/src/qmldevtools/qmldevtools.pro
@@ -19,3 +19,4 @@ include(../3rdparty/masm/masm-defs.pri)
include(../qml/parser/parser.pri)
include(../qml/jsruntime/jsruntime.pri)
include(../qml/compiler/compiler.pri)
+include(../qml/memory/memory.pri)
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 24b87588b8..289a0584e0 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -1,8 +1,8 @@
TARGET = QtQuickTest
DEFINES += QT_NO_URL_CAST_FROM_STRING
-QT = core
-QT_PRIVATE = testlib-private quick qml-private gui core-private
+QT = core testlib-private
+QT_PRIVATE = quick qml-private gui core-private
# Testlib is only a private dependency, which results in our users not
# inheriting testlibs's MODULE_CONFIG transitively. Make it explicit.
diff --git a/src/qmltest/quicktest.h b/src/qmltest/quicktest.h
index 49bd7edfaa..b317a07db4 100644
--- a/src/qmltest/quicktest.h
+++ b/src/qmltest/quicktest.h
@@ -35,9 +35,12 @@
#define QUICKTEST_H
#include <QtQuickTest/quicktestglobal.h>
+#include <QtTest/qtest.h>
QT_BEGIN_NAMESPACE
+QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
+
Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name, const char *sourceDir);
#ifdef QUICK_TEST_SOURCE_DIR
@@ -45,12 +48,16 @@ Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name,
#define QUICK_TEST_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, QUICK_TEST_SOURCE_DIR); \
}
#define QUICK_TEST_OPENGL_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, QUICK_TEST_SOURCE_DIR); \
}
@@ -59,12 +66,16 @@ Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name,
#define QUICK_TEST_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, 0); \
}
#define QUICK_TEST_OPENGL_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, 0); \
}
diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp
index 3f91ce85a8..57ba65e588 100644
--- a/src/qmltest/quicktestresult.cpp
+++ b/src/qmltest/quicktestresult.cpp
@@ -34,6 +34,7 @@
#include "quicktestresult_p.h"
#include <QtTest/qtestcase.h>
#include <QtTest/qtestsystem.h>
+#include <QtTest/private/qtestblacklist_p.h>
#include <QtTest/private/qtestresult_p.h>
#include <QtTest/private/qtesttable_p.h>
#include <QtTest/private/qtestlog_p.h>
@@ -108,6 +109,14 @@ public Q_SLOTS:
pixel += x;
return QColor::fromRgba(*pixel);
}
+
+ bool equals(QuickTestImageObject *other) const
+ {
+ if (!other)
+ return m_image.isNull();
+
+ return m_image == other->m_image;
+ }
private:
QImage m_image;
};
@@ -205,6 +214,7 @@ void QuickTestResult::setFunctionName(const QString &name)
QString fullName = d->testCaseName + QLatin1String("::") + name;
QTestResult::setCurrentTestFunction
(d->intern(fullName).constData());
+ QTestPrivate::checkBlackLists(fullName.toUtf8().constData(), 0);
}
} else {
QTestResult::setCurrentTestFunction(0);
@@ -233,6 +243,7 @@ void QuickTestResult::setDataTag(const QString &tag)
if (!tag.isEmpty()) {
QTestData *data = &(QTest::newRow(tag.toUtf8().constData()));
QTestResult::setCurrentTestData(data);
+ QTestPrivate::checkBlackLists((testCaseName() + QStringLiteral("::") + functionName()).toUtf8().constData(), tag.toUtf8().constData());
emit dataTagChanged();
} else {
QTestResult::setCurrentTestData(0);
@@ -270,6 +281,8 @@ bool QuickTestResult::isSkipped() const
void QuickTestResult::setSkipped(bool skip)
{
QTestResult::setSkipCurrentTest(skip);
+ if (!skip)
+ QTestResult::setBlacklistCurrentTest(false);
emit skippedChanged();
}
@@ -478,8 +491,8 @@ void QuickTestResult::stringify(QQmlV4Function *args)
//Check for Object Type
if (value->isObject()
- && !value->asFunctionObject()
- && !value->asArrayObject()) {
+ && !value->as<QV4::FunctionObject>()
+ && !value->as<QV4::ArrayObject>()) {
QVariant v = scope.engine->toVariant(value, QMetaType::UnknownType);
if (v.isValid()) {
switch (v.type()) {
@@ -500,7 +513,7 @@ void QuickTestResult::stringify(QQmlV4Function *args)
if (result.isEmpty()) {
QString tmp = value->toQStringNoThrow();
- if (value->asArrayObject())
+ if (value->as<QV4::ArrayObject>())
result.append(QString::fromLatin1("[%1]").arg(tmp));
else
result.append(tmp);
@@ -707,6 +720,8 @@ void QuickTestResult::parseArgs(int argc, char *argv[])
void QuickTestResult::setProgramName(const char *name)
{
if (name) {
+ QTestPrivate::parseBlackList();
+ QTestPrivate::parseGpuBlackList();
QTestResult::reset();
} else if (!name && loggingStarted) {
QTestResult::setCurrentTestObject(globalProgramName);
diff --git a/src/qmltest/quicktestresult_p.h b/src/qmltest/quicktestresult_p.h
index 80f84bfa55..45df83621f 100644
--- a/src/qmltest/quicktestresult_p.h
+++ b/src/qmltest/quicktestresult_p.h
@@ -50,7 +50,6 @@ class QuickTestResultPrivate;
class Q_QUICK_TEST_EXPORT QuickTestResult : public QObject
{
Q_OBJECT
- Q_ENUMS(RunMode)
Q_PROPERTY(QString testCaseName READ testCaseName WRITE setTestCaseName NOTIFY testCaseNameChanged)
Q_PROPERTY(QString functionName READ functionName WRITE setFunctionName NOTIFY functionNameChanged)
Q_PROPERTY(QString dataTag READ dataTag WRITE setDataTag NOTIFY dataTagChanged)
@@ -70,6 +69,7 @@ public:
RepeatUntilValidMeasurement,
RunOnce
};
+ Q_ENUM(RunMode)
QString testCaseName() const;
void setTestCaseName(const QString &name);
diff --git a/src/quick/designer/designersupport.cpp b/src/quick/designer/designersupport.cpp
index 56d2badb62..3f66e81ea7 100644
--- a/src/quick/designer/designersupport.cpp
+++ b/src/quick/designer/designersupport.cpp
@@ -213,10 +213,7 @@ bool isValidAnchorName(const QString &name)
bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
{
-#ifndef QT_NO_DYNAMIC_CAST
- Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)));
-#endif
- QQuickItemPrivate *fromItemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem));
+ QQuickItemPrivate *fromItemPrivate = QQuickItemPrivate::get(fromItem);
QQuickAnchors *anchors = fromItemPrivate->anchors();
return anchors->fill() == toItem
|| anchors->centerIn() == toItem
@@ -246,7 +243,7 @@ bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *to
QQuickAnchors *anchors(QQuickItem *item)
{
- QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
return itemPrivate->anchors();
}
@@ -398,7 +395,7 @@ QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
bool DesignerSupport::isComponentComplete(QQuickItem *item)
{
- return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
+ return QQuickItemPrivate::get(item)->componentComplete;
}
int DesignerSupport::borderWidth(QQuickItem *item)
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index cb694c499a..8fa290b953 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -46,7 +46,7 @@
#include <QtCore/QBuffer>
#include <QtCore/qdatetime.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -990,7 +990,7 @@ void QQuickCanvasItem::loadImage(const QUrl& url)
if (!d->pixmaps.contains(fullPathUrl)) {
QQuickPixmap* pix = new QQuickPixmap();
QQmlRefPointer<QQuickCanvasPixmap> canvasPix;
- canvasPix.take(new QQuickCanvasPixmap(pix));
+ canvasPix.adopt(new QQuickCanvasPixmap(pix));
d->pixmaps.insert(fullPathUrl, canvasPix);
pix->load(qmlEngine(this)
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index bcd7072903..4a1a59d61e 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -68,8 +68,6 @@ private:
class QQuickCanvasItem : public QQuickItem
{
Q_OBJECT
- Q_ENUMS(RenderTarget)
- Q_ENUMS(RenderStrategy)
Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged)
Q_PROPERTY(QString contextType READ contextType WRITE setContextType NOTIFY contextTypeChanged)
@@ -85,12 +83,14 @@ public:
Image,
FramebufferObject
};
+ Q_ENUM(RenderTarget)
enum RenderStrategy {
Immediate,
Threaded,
Cooperative
};
+ Q_ENUM(RenderStrategy)
QQuickCanvasItem(QQuickItem *parent = 0);
~QQuickCanvasItem();
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 4aa3b1c8d0..1ebbe3bdac 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -53,7 +53,7 @@
#include <private/qv4object_p.h>
#include <private/qquickwindow_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -884,7 +884,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object
V4_OBJECT2(QQuickJSContext2DPixelData, QV4::Object)
V4_NEEDS_DESTROY
- static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty);
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty);
static void putIndexed(QV4::Managed *m, uint index, const QV4::Value &value);
static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx);
@@ -1379,7 +1379,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx
QV4::ScopedValue value(scope, ctx->argument(0));
- if (value->asObject()) {
+ if (value->as<Object>()) {
QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->d()->context->state.fillStyle = color;
@@ -1488,7 +1488,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c
QV4::ScopedValue value(scope, ctx->argument(0));
- if (value->asObject()) {
+ if (value->as<Object>()) {
QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->d()->context->state.fillStyle = color;
@@ -1719,7 +1719,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon
} else {
QImage patternTexture;
- if (QV4::Object *o = ctx->args()[0].asObject()) {
+ if (const QV4::Object *o = ctx->args()[0].as<Object>()) {
QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data")));
QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s));
if (!!pixelData) {
@@ -2912,7 +2912,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
} else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
QImage img = canvas->toImage();
if (!img.isNull())
- pixmap.take(new QQuickCanvasPixmap(img));
+ pixmap.adopt(new QQuickCanvasPixmap(img));
} else {
V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
@@ -2921,7 +2921,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
if (!!imageData) {
QV4::Scoped<QQuickJSContext2DPixelData> pix(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>());
if (pix && !pix->d()->image.isNull()) {
- pixmap.take(new QQuickCanvasPixmap(pix->d()->image));
+ pixmap.adopt(new QQuickCanvasPixmap(pix->d()->image));
} else {
V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
@@ -3089,12 +3089,12 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::CallContext
return QV4::Encode(r->d()->image.width() * r->d()->image.height() * 4);
}
-QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint index, bool *hasProperty)
+QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<QQuickJSContext2DPixelData>());
- QV4::ExecutionEngine *v4 = static_cast<QQuickJSContext2DPixelData *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QQuickJSContext2DPixelData *>(m)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<QQuickJSContext2DPixelData *>(m));
+ QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<const QQuickJSContext2DPixelData *>(m));
if (index < static_cast<quint32>(r->d()->image.width() * r->d()->image.height() * 4)) {
if (hasProperty)
@@ -3357,7 +3357,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo
qreal pos = ctx->args()[0].toNumber();
QColor color;
- if (ctx->args()[1].asObject()) {
+ if (ctx->args()[1].as<Object>()) {
color = scope.engine->toVariant(ctx->args()[1], qMetaTypeId<QColor>()).value<QColor>();
} else {
color = qt_color_from_string(ctx->args()[1]);
@@ -4235,7 +4235,7 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV4::ExecutionEngine *v4)
gradientProto = proto;
proto = scope.engine->newObject();
- proto->defineAccessorProperty(scope.engine->id_length, QQuickJSContext2DPixelData::proto_get_length, 0);
+ proto->defineAccessorProperty(scope.engine->id_length(), QQuickJSContext2DPixelData::proto_get_length, 0);
pixelArrayProto = proto;
}
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 67d3a2e4fb..78fa26d791 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -48,7 +48,7 @@
#include <private/qv8engine_p.h>
#include <QtCore/QWaitCondition>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
//#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose!
diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp
index f559f166bf..606d4c45da 100644
--- a/src/quick/items/qquickanchors.cpp
+++ b/src/quick/items/qquickanchors.cpp
@@ -414,13 +414,27 @@ void QQuickAnchorsPrivate::updateMe()
void QQuickAnchorsPrivate::updateOnComplete()
{
//optimization to only set initial dependencies once, at completion time
- QSet<QQuickItem *> dependencies;
- dependencies << fill << centerIn
- << left.item << right.item << hCenter.item
- << top.item << bottom.item << vCenter.item << baseline.item;
-
- foreach (QQuickItem *dependency, dependencies)
- addDepend(dependency);
+ QQuickItem *dependencies[9];
+ dependencies[0] = fill;
+ dependencies[1] = centerIn;
+ dependencies[2] = left.item;
+ dependencies[3] = right.item;
+ dependencies[4] = hCenter.item;
+ dependencies[5] = top.item;
+ dependencies[6] = bottom.item;
+ dependencies[7] = vCenter.item;
+ dependencies[8] = baseline.item;
+
+ std::sort(dependencies, dependencies + 9);
+
+ QQuickItem *lastDependency = 0;
+ for (int i = 0; i < 9; ++i) {
+ QQuickItem *dependency = dependencies[i];
+ if (lastDependency != dependency) {
+ addDepend(dependency);
+ lastDependency = dependency;
+ }
+ }
update();
}
diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h
index 4778afc88b..a10ebb4b73 100644
--- a/src/quick/items/qquickanimatedsprite_p.h
+++ b/src/quick/items/qquickanimatedsprite_p.h
@@ -70,12 +70,12 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem
Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged)
- Q_ENUMS(LoopParameters)
public:
explicit QQuickAnimatedSprite(QQuickItem *parent = 0);
enum LoopParameters {
Infinite = -1
};
+ Q_ENUM(LoopParameters)
bool running() const
{
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index f2a172fad3..8a88e3d0d3 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -44,7 +44,6 @@ class QQuickBorderImagePrivate;
class Q_AUTOTEST_EXPORT QQuickBorderImage : public QQuickImageBase
{
Q_OBJECT
- Q_ENUMS(TileMode)
Q_PROPERTY(QQuickScaleGrid *border READ border CONSTANT)
Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
@@ -59,6 +58,7 @@ public:
QQuickScaleGrid *border();
enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
+ Q_ENUM(TileMode)
TileMode horizontalTileMode() const;
void setHorizontalTileMode(TileMode);
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index 4bd4cfc6fd..2b4b2a51d4 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -140,7 +140,6 @@ class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
{
Q_OBJECT
- Q_ENUMS(Axis DragType)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
@@ -160,12 +159,14 @@ public:
~QQuickDrag();
enum DragType { None, Automatic, Internal };
+ Q_ENUM(DragType)
QQuickItem *target() const;
void setTarget(QQuickItem *target);
void resetTarget();
enum Axis { XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
+ Q_ENUM(Axis)
Axis axis() const;
void setAxis(Axis);
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 52142346ab..bfb732554b 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1330,7 +1330,7 @@ void QQuickFlickable::mouseReleaseEvent(QMouseEvent *event)
if (window() && window()->mouseGrabberItem()) {
QPointF localPos = window()->mouseGrabberItem()->mapFromScene(event->windowPos());
QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
- window()->sendEvent(window()->mouseGrabberItem(), mouseEvent.data());
+ QCoreApplication::sendEvent(window(), mouseEvent.data());
}
// And the event has been consumed
@@ -1434,6 +1434,7 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
d->lastPosTime = currentTimestamp;
d->accumulatedWheelPixelDelta += QVector2D(event->pixelDelta());
d->drag(currentTimestamp, event->type(), event->posF(), d->accumulatedWheelPixelDelta, true, !d->scrollingPhase, velocity);
+ event->accept();
}
if (!event->isAccepted())
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index 3c3cd362dd..c974da66d6 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -93,7 +93,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem
Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren)
Q_CLASSINFO("DefaultProperty", "flickableData")
- Q_ENUMS(FlickableDirection)
Q_FLAGS(BoundsBehavior)
public:
@@ -177,6 +176,7 @@ public:
QQuickItem *contentItem();
enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
+ Q_ENUM(FlickableDirection)
FlickableDirection flickableDirection() const;
void setFlickableDirection(FlickableDirection);
diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h
index bd2efe0676..31bfe97923 100644
--- a/src/quick/items/qquickflipable_p.h
+++ b/src/quick/items/qquickflipable_p.h
@@ -47,7 +47,6 @@ class Q_AUTOTEST_EXPORT QQuickFlipable : public QQuickItem
{
Q_OBJECT
- Q_ENUMS(Side)
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)
@@ -64,6 +63,7 @@ public:
void setBack(QQuickItem *);
enum Side { Front, Back };
+ Q_ENUM(Side)
Side side() const;
Q_SIGNALS:
diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp
index c3e5b97baf..18e786fea4 100644
--- a/src/quick/items/qquickframebufferobject.cpp
+++ b/src/quick/items/qquickframebufferobject.cpp
@@ -47,11 +47,13 @@ class QQuickFramebufferObjectPrivate : public QQuickItemPrivate
public:
QQuickFramebufferObjectPrivate()
: followsItemSize(true)
+ , mirrorVertically(false)
, node(0)
{
}
bool followsItemSize;
+ bool mirrorVertically;
mutable QSGFramebufferObjectNode *node;
};
@@ -138,6 +140,34 @@ bool QQuickFramebufferObject::textureFollowsItemSize() const
}
/*!
+ * \property QQuickFramebufferObject::mirrorVertically
+ *
+ * This property controls if the size of the FBO's contents should be mirrored
+ * vertically when drawing. This allows easy integration of third-party
+ * rendering code that does not follow the standard expectations.
+ *
+ * The default value is \c {false}.
+ *
+ * \since 5.6
+ */
+
+void QQuickFramebufferObject::setMirrorVertically(bool enable)
+{
+ Q_D(QQuickFramebufferObject);
+ if (d->mirrorVertically == enable)
+ return;
+ d->mirrorVertically = enable;
+ emit mirrorVerticallyChanged(d->mirrorVertically);
+ update();
+}
+
+bool QQuickFramebufferObject::mirrorVertically() const
+{
+ Q_D(const QQuickFramebufferObject);
+ return d->mirrorVertically;
+}
+
+/*!
* \internal
*/
void QQuickFramebufferObject::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
@@ -290,6 +320,7 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode
QQuickWindow::TextureHasAlphaChannel));
}
+ n->setTextureCoordinatesTransform(d->mirrorVertically ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform);
n->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
n->setRect(0, 0, width(), height());
diff --git a/src/quick/items/qquickframebufferobject.h b/src/quick/items/qquickframebufferobject.h
index 4a0248c082..7fb7262222 100644
--- a/src/quick/items/qquickframebufferobject.h
+++ b/src/quick/items/qquickframebufferobject.h
@@ -49,6 +49,7 @@ class Q_QUICK_EXPORT QQuickFramebufferObject : public QQuickItem
Q_DECLARE_PRIVATE(QQuickFramebufferObject)
Q_PROPERTY(bool textureFollowsItemSize READ textureFollowsItemSize WRITE setTextureFollowsItemSize NOTIFY textureFollowsItemSizeChanged)
+ Q_PROPERTY(bool mirrorVertically READ mirrorVertically WRITE setMirrorVertically NOTIFY mirrorVerticallyChanged)
public:
@@ -73,6 +74,9 @@ public:
bool textureFollowsItemSize() const;
void setTextureFollowsItemSize(bool follows);
+ bool mirrorVertically() const;
+ void setMirrorVertically(bool enable);
+
virtual Renderer *createRenderer() const = 0;
bool isTextureProvider() const Q_DECL_OVERRIDE;
@@ -87,6 +91,7 @@ protected:
Q_SIGNALS:
void textureFollowsItemSizeChanged(bool);
+ void mirrorVerticallyChanged(bool);
private Q_SLOTS:
void invalidateSceneGraph();
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 3cc0a28b87..e3f216b3a2 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -267,9 +267,13 @@ qreal QQuickGridViewPrivate::originPosition() const
qreal QQuickGridViewPrivate::lastPosition() const
{
qreal pos = 0;
- if (model && model->count()) {
- // get end position of last item
- pos = (rowPosAt(model->count() - 1) + rowSize());
+ if (model && (model->count() || !visibleItems.isEmpty())) {
+ qreal lastRowPos = model->count() ? rowPosAt(model->count() - 1) : 0;
+ if (!visibleItems.isEmpty()) {
+ // If there are items in delayRemove state, they may be after any items linked to the model
+ lastRowPos = qMax(lastRowPos, static_cast<FxGridItemSG*>(visibleItems.last())->rowPos());
+ }
+ pos = lastRowPos + rowSize();
}
return pos;
}
diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h
index 7e1ace01dd..389ef27585 100644
--- a/src/quick/items/qquickgridview_p.h
+++ b/src/quick/items/qquickgridview_p.h
@@ -52,8 +52,6 @@ class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
- Q_ENUMS(SnapMode)
- Q_ENUMS(Flow)
Q_CLASSINFO("DefaultProperty", "data")
public:
@@ -61,6 +59,7 @@ public:
FlowLeftToRight = LeftToRight,
FlowTopToBottom = TopToBottom
};
+ Q_ENUM(Flow)
QQuickGridView(QQuickItem *parent=0);
~QQuickGridView();
@@ -78,6 +77,7 @@ public:
void setCellHeight(qreal);
enum SnapMode { NoSnap, SnapToRow, SnapOneRow };
+ Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index 8edf153ca3..a780f9a626 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -40,12 +40,9 @@
QT_BEGIN_NAMESPACE
class QQuickImagePrivate;
-class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase
+class Q_QUICK_PRIVATE_EXPORT QQuickImage : public QQuickImageBase
{
Q_OBJECT
- Q_ENUMS(FillMode)
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged)
@@ -62,11 +59,14 @@ public:
enum HAlignment { AlignLeft = Qt::AlignLeft,
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter };
+ Q_ENUM(HAlignment)
enum VAlignment { AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter };
+ Q_ENUM(VAlignment)
enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally, Pad };
+ Q_ENUM(FillMode)
FillMode fillMode() const;
void setFillMode(FillMode);
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 223cb8f46f..e54f5bb9c9 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -213,15 +213,27 @@ void QQuickImageBase::load()
d->devicePixelRatio = 1.0;
QUrl loadUrl = d->url;
- if (d->url.scheme() == QStringLiteral("image")
- || d->url.toString().endsWith(QLatin1String(".svg"))
- || d->url.toString().endsWith(QLatin1String(".svgz"))) {
- // QQuickImageProvider and SVG can generate a high resolution image when
- // sourceSize is set. If sourceSize is not set then the provider default size
- // will be used, as usual.
- if (!d->sourcesize.isEmpty())
+
+ // QQuickImageProvider and SVG can generate a high resolution image when
+ // sourceSize is set. If sourceSize is not set then the provider default size
+ // will be used, as usual.
+ bool setDevicePixelRatio = false;
+ if (!d->sourcesize.isValid()) {
+ if (loadUrl.scheme() == QStringLiteral("image")) {
+ setDevicePixelRatio = true;
+ } else {
+ QString stringUrl = loadUrl.toString();
+ if (stringUrl.endsWith(QLatin1String("svg")) ||
+ stringUrl.endsWith(QLatin1String("svgz"))) {
+ setDevicePixelRatio = true;
+ }
+ }
+
+ if (setDevicePixelRatio)
d->devicePixelRatio = targetDevicePixelRatio;
- } else {
+ }
+
+ if (!setDevicePixelRatio) {
// (possible) local file: loadUrl and d->devicePixelRatio will be modified if
// an "@2x" file is found.
resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio);
@@ -368,7 +380,7 @@ void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixe
// Look for an @2x version
QString localFile2x = image2xPath(localFile);
- if (!QFile(localFile2x).exists())
+ if (!QFile::exists(localFile2x))
return;
// @2x file found found: Change url and devicePixelRatio
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 4fcfaecd7d..98943a235c 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -43,7 +43,6 @@ class QQuickImageBasePrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickImageBase : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(Status)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
@@ -57,6 +56,7 @@ public:
QQuickImageBase(QQuickItem *parent=0);
~QQuickImageBase();
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
qreal progress() const;
diff --git a/src/quick/items/qquickimplicitsizeitem_p_p.h b/src/quick/items/qquickimplicitsizeitem_p_p.h
index f2e502af15..d606474e9d 100644
--- a/src/quick/items/qquickimplicitsizeitem_p_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p_p.h
@@ -51,7 +51,7 @@
QT_BEGIN_NAMESPACE
-class QQuickImplicitSizeItemPrivate : public QQuickItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickImplicitSizeItemPrivate : public QQuickItemPrivate
{
Q_DECLARE_PUBLIC(QQuickImplicitSizeItem)
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 3d0f550d14..94b89d0fc4 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -1304,8 +1304,8 @@ void QQuickKeysAttached::setPriority(Priority order)
void QQuickKeysAttached::componentComplete()
{
- Q_D(QQuickKeysAttached);
#ifndef QT_NO_IM
+ Q_D(QQuickKeysAttached);
if (d->item) {
for (int ii = 0; ii < d->targets.count(); ++ii) {
QQuickItem *targetItem = d->targets.at(ii);
@@ -2776,7 +2776,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c)
window = c;
if (polishScheduled)
- QQuickWindowPrivate::get(window)->itemsToPolish.insert(q);
+ QQuickWindowPrivate::get(window)->itemsToPolish.append(q);
if (!parentItem)
QQuickWindowPrivate::get(window)->parentlessItems.insert(q);
@@ -2808,7 +2808,7 @@ void QQuickItemPrivate::derefWindow()
removeFromDirtyList();
QQuickWindowPrivate *c = QQuickWindowPrivate::get(window);
if (polishScheduled)
- c->itemsToPolish.remove(q);
+ c->itemsToPolish.removeOne(q);
QMutableHashIterator<int, QQuickItem *> itemTouchMapIt(c->itemForTouchPointId);
while (itemTouchMapIt.hasNext()) {
if (itemTouchMapIt.next().value() == q)
@@ -4102,7 +4102,7 @@ void QQuickItem::polish()
if (d->window) {
QQuickWindowPrivate *p = QQuickWindowPrivate::get(d->window);
bool maybeupdate = p->itemsToPolish.isEmpty();
- p->itemsToPolish.insert(this);
+ p->itemsToPolish.append(this);
if (maybeupdate) d->window->maybeUpdate();
}
}
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 463113386b..d92910ce9c 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -141,7 +141,6 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL)
- Q_ENUMS(TransformOrigin)
Q_CLASSINFO("DefaultProperty", "data")
Q_CLASSINFO("qt_HasQmlAccessors", "true")
@@ -187,6 +186,7 @@ public:
Left, Center, Right,
BottomLeft, Bottom, BottomRight
};
+ Q_ENUM(TransformOrigin)
QQuickItem(QQuickItem *parent = 0);
virtual ~QQuickItem();
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 64d8bd0ede..c0d06da829 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -645,8 +645,6 @@ 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)
- Q_ENUMS(Priority)
-
public:
QQuickKeyNavigationAttached(QObject * = 0);
@@ -664,6 +662,7 @@ public:
void setBacktab(QQuickItem *);
enum Priority { BeforeItem, AfterItem };
+ Q_ENUM(Priority)
Priority priority() const;
void setPriority(Priority);
@@ -739,8 +738,6 @@ class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
Q_PROPERTY(QQmlListProperty<QQuickItem> forwardTo READ forwardTo)
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
- Q_ENUMS(Priority)
-
public:
QQuickKeysAttached(QObject *parent=0);
~QQuickKeysAttached();
@@ -755,6 +752,7 @@ public:
}
enum Priority { BeforeItem, AfterItem};
+ Q_ENUM(Priority)
Priority priority() const;
void setPriority(Priority);
diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h
index 907687a2bd..9f0b3dccb8 100644
--- a/src/quick/items/qquickitemanimation_p.h
+++ b/src/quick/items/qquickitemanimation_p.h
@@ -136,7 +136,7 @@ public:
BottomFirst,
TopFirst
};
- Q_ENUMS(Orientation)
+ Q_ENUM(Orientation)
int duration() const;
void setDuration(int);
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 5fbae66b6c..8a6766770e 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -158,11 +158,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView");
qmlRegisterUncreatableType<QQuickBasePositioner>(uri,major,minor,"Positioner",
QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
-#ifndef QT_NO_VALIDATOR
- qmlRegisterType<QQuickIntValidator>(uri,major,minor,"IntValidator");
- qmlRegisterType<QQuickDoubleValidator>(uri,major,minor,"DoubleValidator");
- qmlRegisterType<QRegExpValidator>(uri,major,minor,"RegExpValidator");
-#endif
qmlRegisterType<QQuickRectangle>(uri,major,minor,"Rectangle");
qmlRegisterType<QQuickRepeater>(uri,major,minor,"Repeater");
qmlRegisterType<QQuickRow>(uri,major,minor,"Row");
@@ -190,9 +185,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickCurve>();
qmlRegisterType<QQuickScaleGrid>();
qmlRegisterType<QQuickTextLine>();
-#ifndef QT_NO_VALIDATOR
- qmlRegisterType<QValidator>();
-#endif
qmlRegisterType<QQuickPen>();
qmlRegisterType<QQuickFlickableVisibleArea>();
qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine");
@@ -269,6 +261,16 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickPinchArea, 1>(uri, 2, 5,"PinchArea");
qmlRegisterType<QQuickImage, 2>(uri, 2, 5,"Image");
qmlRegisterType<QQuickMouseArea, 2>(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");
+ 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");
}
static void initResources()
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 01ef1e65f7..7a55bd6e0a 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -71,19 +71,19 @@ FxViewItem::~FxViewItem()
qreal FxViewItem::itemX() const
{
- return transitionableItem ? transitionableItem->itemX() : item->x();
+ return transitionableItem ? transitionableItem->itemX() : (item ? item->x() : 0);
}
qreal FxViewItem::itemY() const
{
- return transitionableItem ? transitionableItem->itemY() : item->y();
+ return transitionableItem ? transitionableItem->itemY() : (item ? item->y() : 0);
}
void FxViewItem::moveTo(const QPointF &pos, bool immediate)
{
if (transitionableItem)
transitionableItem->moveTo(pos, immediate);
- else
+ else if (item)
item->setPosition(pos);
}
@@ -91,21 +91,26 @@ void FxViewItem::setVisible(bool visible)
{
if (!visible && transitionableItem && transitionableItem->transitionScheduledOrRunning())
return;
- QQuickItemPrivate::get(item)->setCulled(!visible);
+ if (item)
+ QQuickItemPrivate::get(item)->setCulled(!visible);
}
void FxViewItem::trackGeometry(bool track)
{
if (track) {
if (!trackGeom) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ if (item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ }
trackGeom = true;
}
} else {
if (trackGeom) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ if (item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ }
trackGeom = false;
}
}
@@ -1199,7 +1204,7 @@ void QQuickItemView::destroyRemoved()
for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
it != d->visibleItems.end();) {
FxViewItem *item = *it;
- if (item->index == -1 && item->attached->delayRemove() == false) {
+ if (item->index == -1 && (!item->attached || item->attached->delayRemove() == false)) {
if (d->transitioner && d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) {
// don't remove from visibleItems until next layout()
d->runDelayedRemoveTransition = true;
@@ -1344,7 +1349,7 @@ void QQuickItemView::geometryChanged(const QRectF &newGeometry, const QRectF &ol
{
Q_D(QQuickItemView);
d->markExtentsDirty();
- if (isComponentComplete() && d->isValid())
+ if (isComponentComplete() && (d->isValid() || !d->visibleItems.isEmpty()))
d->forceLayoutPolish();
QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
}
@@ -1641,7 +1646,8 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex)
applyPendingChanges();
if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
if (currentItem) {
- currentItem->attached->setIsCurrentItem(false);
+ if (currentItem->attached)
+ currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
currentIndex = modelIndex;
@@ -1664,11 +1670,12 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex)
int oldCurrentIndex = currentIndex;
currentIndex = modelIndex;
currentItem = createItem(modelIndex, false);
- if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item))
oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
currentItem->item->setFocus(true);
- currentItem->attached->setIsCurrentItem(true);
+ if (currentItem->attached)
+ currentItem->attached->setIsCurrentItem(true);
initializeCurrentItem();
}
@@ -1806,7 +1813,7 @@ void QQuickItemViewPrivate::updateViewport()
{
Q_Q(QQuickItemView);
qreal extra = headerSize() + footerSize();
- qreal contentSize = isValid() ? (endPosition() - startPosition()) : 0.0;
+ qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
if (layoutOrientation() == Qt::Vertical)
q->setContentHeight(contentSize + extra);
else
@@ -1824,6 +1831,7 @@ void QQuickItemViewPrivate::layout()
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartOffset());
+ updateViewport();
if (transitioner)
transitioner->setPopulateTransitionEnabled(false);
inLayout = false;
@@ -1967,7 +1975,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
QQmlChangeSet::Change removal;
for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
FxViewItem *item = *it;
- if (item->index == -1 && !item->attached->delayRemove()) {
+ if (item->index == -1 && (!item->attached || !item->attached->delayRemove())) {
removeItem(item, removal, &removalResult);
removedCount++;
it = visibleItems.erase(it);
@@ -2007,8 +2015,10 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
}
itemCount += insertions[i].count;
}
- for (int i=0; i<newItems.count(); i++)
- newItems.at(i)->attached->emitAdd();
+ for (int i=0; i<newItems.count(); i++) {
+ if (newItems.at(i)->attached)
+ newItems.at(i)->attached->emitAdd();
+ }
// for each item that was moved directly into the view as a result of a move(),
// find the index it was moved from in order to set its initial position, so that we
@@ -2040,7 +2050,8 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
if (currentChanges.currentChanged) {
if (currentChanges.currentRemoved && currentItem) {
- currentItem->attached->setIsCurrentItem(false);
+ if (currentItem->item && currentItem->attached)
+ currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
}
@@ -2092,10 +2103,10 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QQmlChangeSet::Change &remo
} else {
// removed item
visibleAffected = true;
- if (!removal.isMove())
+ if (!removal.isMove() && item->item && item->attached)
item->attached->emitRemove();
- if (item->attached->delayRemove() && !removal.isMove()) {
+ if (item->item && item->attached && item->attached->delayRemove() && !removal.isMove()) {
item->index = -1;
QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
++it;
@@ -2352,12 +2363,14 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item)
item->trackGeometry(false);
QQmlInstanceModel::ReleaseFlags flags = model->release(item->item);
- if (flags == 0) {
- // item was not destroyed, and we no longer reference it.
- QQuickItemPrivate::get(item->item)->setCulled(true);
- unrequestedItems.insert(item->item, model->indexOf(item->item, q));
- } else if (flags & QQmlInstanceModel::Destroyed) {
- item->item->setParentItem(0);
+ if (item->item) {
+ if (flags == 0) {
+ // item was not destroyed, and we no longer reference it.
+ QQuickItemPrivate::get(item->item)->setCulled(true);
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ } else if (flags & QQmlInstanceModel::Destroyed) {
+ item->item->setParentItem(0);
+ }
}
delete item;
return flags != QQmlInstanceModel::Referenced;
@@ -2421,7 +2434,7 @@ void QQuickItemViewPrivate::updateUnrequestedIndexes()
void QQuickItemViewPrivate::updateUnrequestedPositions()
{
- for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.begin(), cend = unrequestedItems.end(); it != cend; ++it)
+ for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it)
repositionPackageItemAt(it.key(), it.value());
}
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index 6e5ae032c2..3e28ff336d 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -88,11 +88,6 @@ class Q_AUTOTEST_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)
- Q_ENUMS(HighlightRangeMode)
- Q_ENUMS(PositionMode)
- Q_ENUMS(VerticalLayoutDirection)
- Q_ENUMS(LayoutDirection)
-
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
@@ -103,11 +98,13 @@ public:
VerticalTopToBottom,
VerticalBottomToTop
};
+ Q_ENUM(LayoutDirection)
enum VerticalLayoutDirection {
TopToBottom = VerticalTopToBottom,
BottomToTop = VerticalBottomToTop
};
+ Q_ENUM(VerticalLayoutDirection)
QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent = 0);
~QQuickItemView();
@@ -185,6 +182,7 @@ public:
virtual void setHighlightFollowsCurrentItem(bool);
enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ Q_ENUM(HighlightRangeMode)
HighlightRangeMode highlightRangeMode() const;
void setHighlightRangeMode(HighlightRangeMode mode);
@@ -200,6 +198,7 @@ public:
virtual void setHighlightMoveDuration(int);
enum PositionMode { Beginning, Center, End, Visible, Contain, SnapPosition };
+ Q_ENUM(PositionMode)
Q_INVOKABLE void positionViewAtIndex(int index, int mode);
Q_INVOKABLE int indexAt(qreal x, qreal y) const;
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index 5ac88a7585..67ef413d31 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -53,6 +53,8 @@ public:
qreal itemX() const;
qreal itemY() const;
+ inline qreal itemWidth() const { return item ? item->width() : 0; }
+ inline qreal itemHeight() const { return item ? item->height() : 0; }
void moveTo(const QPointF &pos, bool immediate);
void setVisible(bool visible);
@@ -75,7 +77,7 @@ public:
virtual bool contains(qreal x, qreal y) const = 0;
- QQuickItem *item;
+ QPointer<QQuickItem> item;
QQuickItemView *view;
QQuickItemViewTransitionableItem *transitionableItem;
QQuickItemViewAttached *attached;
diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp
index 7fa6cdc161..6fa299bf03 100644
--- a/src/quick/items/qquickitemviewtransition.cpp
+++ b/src/quick/items/qquickitemviewtransition.cpp
@@ -34,6 +34,7 @@
#include "qquickitemviewtransition_p.h"
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h
index 170072a814..6f93697cc5 100644
--- a/src/quick/items/qquickitemviewtransition_p.h
+++ b/src/quick/items/qquickitemviewtransition_p.h
@@ -34,16 +34,20 @@
#ifndef QQUICKITEMVIEWTRANSITION_P_P_H
#define QQUICKITEMVIEWTRANSITION_P_P_H
-#include <private/qquicktransitionmanager_p_p.h>
+#include <QtQuick/private/qtquickglobal_p.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qpoint.h>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
class QQuickItem;
+class QQuickTransition;
class QQuickItemViewTransitionableItem;
class QQuickItemViewTransitionJob;
-class QQuickItemViewTransitionChangeListener
+class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionChangeListener
{
public:
QQuickItemViewTransitionChangeListener() {}
@@ -53,7 +57,7 @@ public:
};
-class QQuickItemViewTransitioner
+class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitioner
{
public:
enum TransitionType {
@@ -113,7 +117,7 @@ private:
/*
An item that can be transitioned using QQuickViewTransitionJob.
*/
-class QQuickItemViewTransitionableItem
+class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionableItem
{
public:
QQuickItemViewTransitionableItem(QQuickItem *i);
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index cc500956f5..a2920f8bad 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -267,18 +267,18 @@ public:
}
qreal itemPosition() const {
if (view->orientation() == QQuickListView::Vertical)
- return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -item->height()-itemY() : itemY());
+ return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -itemHeight()-itemY() : itemY());
else
- return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-itemX() : itemX());
+ return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -itemWidth()-itemX() : itemX());
}
qreal size() const {
if (section())
- return (view->orientation() == QQuickListView::Vertical ? item->height()+section()->height() : item->width()+section()->width());
+ return (view->orientation() == QQuickListView::Vertical ? itemHeight()+section()->height() : itemWidth()+section()->width());
else
- return (view->orientation() == QQuickListView::Vertical ? item->height() : item->width());
+ return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth());
}
qreal itemSize() const {
- return (view->orientation() == QQuickListView::Vertical ? item->height() : item->width());
+ return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth());
}
qreal sectionSize() const {
if (section())
@@ -289,11 +289,11 @@ public:
if (view->orientation() == QQuickListView::Vertical) {
return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop
? -itemY()
- : itemY() + item->height());
+ : itemY() + itemHeight());
} else {
return (view->effectiveLayoutDirection() == Qt::RightToLeft
? -itemX()
- : itemX() + item->width());
+ : itemX() + itemWidth());
}
}
void setPosition(qreal pos, bool immediate = false) {
@@ -320,8 +320,8 @@ public:
item->setWidth(size);
}
bool contains(qreal x, qreal y) const Q_DECL_OVERRIDE {
- return (x >= itemX() && x < itemX() + item->width() &&
- y >= itemY() && y < itemY() + item->height());
+ return (x >= itemX() && x < itemX() + itemWidth() &&
+ y >= itemY() && y < itemY() + itemHeight());
}
QQuickListView *view;
@@ -332,7 +332,7 @@ private:
if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop) {
if (section())
pos += section()->height();
- return QPointF(itemX(), -item->height() - pos);
+ return QPointF(itemX(), -itemHeight() - pos);
} else {
if (section())
pos += section()->height();
@@ -342,7 +342,7 @@ private:
if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
if (section())
pos += section()->width();
- return QPointF(-item->width() - pos, itemY());
+ return QPointF(-itemWidth() - pos, itemY());
} else {
if (section())
pos += section()->width();
@@ -427,14 +427,24 @@ qreal QQuickListViewPrivate::lastPosition() const
{
qreal pos = 0;
if (!visibleItems.isEmpty()) {
- int invisibleCount = visibleItems.count() - visibleIndex;
+ int invisibleCount = INT_MIN;
+ int delayRemovedCount = 0;
for (int i = visibleItems.count()-1; i >= 0; --i) {
if (visibleItems.at(i)->index != -1) {
- invisibleCount = model->count() - visibleItems.at(i)->index - 1;
+ // Find the invisible count after the last visible item with known index
+ invisibleCount = model->count() - (visibleItems.at(i)->index + 1 + delayRemovedCount);
break;
+ } else if (visibleItems.at(i)->attached->delayRemove()) {
+ ++delayRemovedCount;
}
}
- pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
+ if (invisibleCount == INT_MIN) {
+ // All visible items are in delayRemove state
+ invisibleCount = model->count();
+ }
+ pos = (*(--visibleItems.constEnd()))->endPosition();
+ if (invisibleCount > 0)
+ pos += invisibleCount * (averageSize + spacing);
} else if (model && model->count()) {
pos = (model->count() * averageSize + (model->count()-1) * spacing);
}
@@ -602,7 +612,7 @@ bool QQuickListViewPrivate::releaseItem(FxViewItem *item)
QQuickListViewAttached *att = static_cast<QQuickListViewAttached*>(item->attached);
bool released = QQuickItemViewPrivate::releaseItem(item);
- if (released && att && att->m_sectionItem) {
+ if (released && item->item && att && att->m_sectionItem) {
// We hold no more references to this item
int i = 0;
do {
@@ -657,10 +667,11 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
while (modelIndex < model->count() && pos <= fillTo) {
if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer))))
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(pos, true);
- QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
+ if (item->item)
+ QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
pos += item->size() + spacing;
visibleItems.append(item);
++modelIndex;
@@ -673,12 +684,13 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, doBuffer))))
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
--visibleIndex;
visiblePos -= item->size() + spacing;
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(visiblePos, true);
- QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
+ if (item->item)
+ QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
visibleItems.prepend(item);
changed = true;
}
@@ -709,7 +721,7 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
visibleIndex++;
visibleItems.removeAt(index);
if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << (QObject *)(item->item);
item->releaseAfterTransition = true;
releasePendingTransition.append(item);
} else {
@@ -728,10 +740,10 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
if (item->attached->delayRemove())
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << (QObject *)(item->item);
visibleItems.removeLast();
if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << (QObject *)(item->item);
item->releaseAfterTransition = true;
releasePendingTransition.append(item);
} else {
@@ -2844,7 +2856,8 @@ void QQuickListView::viewportMoved(Qt::Orientations orient)
qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
- QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
+ if (item->item)
+ QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
}
if (d->currentItem)
QQuickItemPrivate::get(d->currentItem->item)->setCulled(d->currentItem->endPosition() < from || d->currentItem->position() > to);
diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h
index bcb4e18751..7f64e12bba 100644
--- a/src/quick/items/qquicklistview_p.h
+++ b/src/quick/items/qquicklistview_p.h
@@ -47,8 +47,6 @@ class Q_AUTOTEST_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)
- Q_ENUMS(SectionCriteria)
- Q_ENUMS(LabelPositioning)
public:
QQuickViewSection(QQuickListView *parent=0);
@@ -56,6 +54,7 @@ public:
void setProperty(const QString &);
enum SectionCriteria { FullString, FirstCharacter };
+ Q_ENUM(SectionCriteria)
SectionCriteria criteria() const { return m_criteria; }
void setCriteria(SectionCriteria);
@@ -65,6 +64,7 @@ public:
QString sectionString(const QString &value);
enum LabelPositioning { InlineLabels = 0x01, CurrentLabelAtStart = 0x02, NextLabelAtEnd = 0x04 };
+ Q_ENUM(LabelPositioning)
int labelPositioning() { return m_labelPositioning; }
void setLabelPositioning(int pos);
@@ -106,10 +106,6 @@ class Q_AUTOTEST_EXPORT QQuickListView : public QQuickItemView
Q_PROPERTY(HeaderPositioning headerPositioning READ headerPositioning WRITE setHeaderPositioning NOTIFY headerPositioningChanged REVISION 2)
Q_PROPERTY(FooterPositioning footerPositioning READ footerPositioning WRITE setFooterPositioning NOTIFY footerPositioningChanged REVISION 2)
- Q_ENUMS(Orientation)
- Q_ENUMS(SnapMode)
- Q_ENUMS(HeaderPositioning)
- Q_ENUMS(FooterPositioning)
Q_CLASSINFO("DefaultProperty", "data")
public:
@@ -120,6 +116,7 @@ public:
void setSpacing(qreal spacing);
enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
+ Q_ENUM(Orientation)
Orientation orientation() const;
void setOrientation(Orientation);
@@ -140,14 +137,17 @@ public:
void setHighlightMoveDuration(int) Q_DECL_OVERRIDE;
enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
enum HeaderPositioning { InlineHeader, OverlayHeader, PullBackHeader };
+ Q_ENUM(HeaderPositioning)
HeaderPositioning headerPositioning() const;
void setHeaderPositioning(HeaderPositioning positioning);
enum FooterPositioning { InlineFooter, OverlayFooter, PullBackFooter };
+ Q_ENUM(FooterPositioning)
FooterPositioning footerPositioning() const;
void setFooterPositioning(FooterPositioning positioning);
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index dd04568db2..df09780895 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -943,7 +943,7 @@ QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Funct
QV4::ScopedValue valuemap(scope, QV4::Primitive::undefinedValue());
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
- if (!v->isObject() || v->asArrayObject()) {
+ if (!v->isObject() || v->as<QV4::ArrayObject>()) {
*error = true;
qmlInfo(loader) << QQuickLoader::tr("setSource: value is not an object");
} else {
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
index 2c0e98de59..6ed4f2437b 100644
--- a/src/quick/items/qquickloader_p.h
+++ b/src/quick/items/qquickloader_p.h
@@ -42,7 +42,6 @@ class QQuickLoaderPrivate;
class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(Status)
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
@@ -69,6 +68,7 @@ public:
void resetSourceComponent();
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
qreal progress() const;
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 621419d1a7..fb1263f0bd 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -50,7 +50,7 @@
#include "qquickitemchangelistener_p.h"
#include <qqmlincubator.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickopenglinfo_p.h b/src/quick/items/qquickopenglinfo_p.h
index 2a2e2a719b..511413c814 100644
--- a/src/quick/items/qquickopenglinfo_p.h
+++ b/src/quick/items/qquickopenglinfo_p.h
@@ -63,7 +63,6 @@ class QQuickOpenGLInfo : public QObject
Q_PROPERTY(int minorVersion READ minorVersion NOTIFY minorVersionChanged FINAL)
Q_PROPERTY(ContextProfile profile READ profile NOTIFY profileChanged FINAL)
Q_PROPERTY(RenderableType renderableType READ renderableType NOTIFY renderableTypeChanged FINAL)
- Q_ENUMS(ContextProfile RenderableType)
public:
QQuickOpenGLInfo(QQuickItem *item = 0);
@@ -77,6 +76,7 @@ public:
CoreProfile = QSurfaceFormat::CoreProfile,
CompatibilityProfile = QSurfaceFormat::CompatibilityProfile
};
+ Q_ENUM(ContextProfile)
ContextProfile profile() const;
// keep in sync with QSurfaceFormat::RenderableType
@@ -85,6 +85,7 @@ public:
OpenGL = QSurfaceFormat::OpenGL,
OpenGLES = QSurfaceFormat::OpenGLES
};
+ Q_ENUM(RenderableType)
RenderableType renderableType() const;
static QQuickOpenGLInfo *qmlAttachedProperties(QObject *object);
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index 356e4a46f6..28eb3398a0 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -43,7 +43,6 @@ class QQuickPaintedItemPrivate;
class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem
{
Q_OBJECT
- Q_ENUMS(RenderTarget)
Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged)
Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
@@ -58,6 +57,7 @@ public:
FramebufferObject,
InvertedYFramebufferObject
};
+ Q_ENUM(RenderTarget)
enum PerformanceHint {
FastFBOResizing = 0x1
diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h
index 3712e964f8..2759d9d683 100644
--- a/src/quick/items/qquickpainteditem_p.h
+++ b/src/quick/items/qquickpainteditem_p.h
@@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE
class QQuickPaintedItemTextureProvider;
class QSGPainterNode;
-class QQuickPaintedItemPrivate : public QQuickItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickPaintedItemPrivate : public QQuickItemPrivate
{
public:
QQuickPaintedItemPrivate();
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 58605f79dd..302532c3d1 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -98,7 +98,7 @@ QQuickPathViewPrivate::QQuickPathViewPrivate()
, inRefill(false)
, dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY)
, moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0)
- , firstIndex(-1), pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0)
+ , pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0)
, moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0)
, moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition)
, highlightPosition(0)
@@ -447,7 +447,6 @@ void QQuickPathViewPrivate::regenerate()
if (!isValid())
return;
- firstIndex = -1;
updateMappedRange();
q->refill();
}
@@ -1473,7 +1472,7 @@ int QQuickPathView::indexAt(qreal x, qreal y) const
QQuickItem *item = d->items.at(idx);
QPointF p = item->mapFromItem(this, QPointF(x, y));
if (item->contains(p))
- return (d->firstIndex + idx) % d->modelCount;
+ return d->model->indexOf(item, 0);
}
return -1;
@@ -1896,12 +1895,12 @@ void QQuickPathView::refill()
int count = d->pathItems == -1 ? d->modelCount : qMin(d->pathItems, d->modelCount);
// first move existing items and remove items off path
- int idx = d->firstIndex;
- qCDebug(lcItemViewDelegateLifecycle) << "firstIndex" << idx << "currentIndex" << d->currentIndex << "offset" << d->offset;
+ qCDebug(lcItemViewDelegateLifecycle) << "currentIndex" << d->currentIndex << "offset" << d->offset;
QList<QQuickItem*>::iterator it = d->items.begin();
while (it != d->items.end()) {
- qreal pos = d->positionOfIndex(idx);
QQuickItem *item = *it;
+ int idx = d->model->indexOf(item, 0);
+ qreal pos = d->positionOfIndex(idx);
if (lcItemViewDelegateLifecycle().isDebugEnabled()) {
QQuickText *text = qmlobject_cast<QQuickText*>(item);
if (text)
@@ -1923,81 +1922,140 @@ void QQuickPathView::refill()
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);
d->releaseItem(item);
- if (it == d->items.begin()) {
- if (++d->firstIndex >= d->modelCount) {
- d->firstIndex = 0;
- }
- }
it = d->items.erase(it);
} else {
++it;
}
}
- ++idx;
- if (idx >= d->modelCount)
- idx = 0;
}
- if (!d->items.count())
- d->firstIndex = -1;
-
bool waiting = false;
if (d->modelCount) {
- // add items to beginning and end
+ // add items as needed
if (d->items.count() < count+d->cacheSize) {
- int idx = qRound(d->modelCount - d->offset) % d->modelCount;
+ int endIdx = 0;
+ qreal endPos;
+ int startIdx = 0;
qreal startPos = 0.0;
- if (d->haveHighlightRange && (d->highlightRangeMode != QQuickPathView::NoHighlightRange
- || d->snapMode != QQuickPathView::NoSnap))
- startPos = d->highlightRangeStart;
- if (d->firstIndex >= 0) {
- startPos = d->positionOfIndex(d->firstIndex);
- idx = (d->firstIndex + d->items.count()) % d->modelCount;
+ if (d->items.count()) {
+ //Find the beginning and end, items may not be in sorted order
+ endPos = -1.0;
+ startPos = 2.0;
+
+ for (int i = 0; i < d->items.count(); i++) {
+ int idx = d->model->indexOf(d->items[i], 0);
+ qreal curPos = d->positionOfIndex(idx);
+ if (curPos > endPos) {
+ endPos = curPos;
+ endIdx = idx;
+ }
+
+ if (curPos < startPos) {
+ startPos = curPos;
+ startIdx = idx;
+ }
+ }
+ } else {
+ if (d->haveHighlightRange
+ && (d->highlightRangeMode != QQuickPathView::NoHighlightRange
+ || d->snapMode != QQuickPathView::NoSnap))
+ startPos = d->highlightRangeStart;
+ // With no items, then "end" is just off the top so we populate via append
+ endIdx = (qRound(d->modelCount - d->offset) - 1) % d->modelCount;
+ endPos = d->positionOfIndex(endIdx);
}
- qreal pos = d->positionOfIndex(idx);
- while ((d->isInBound(pos, startPos, 1.0 + d->mappedCache) || !d->items.count()) && d->items.count() < count+d->cacheSize) {
- qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
- QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0);
+ //Append
+ int idx = endIdx + 1;
+ if (idx >= d->modelCount)
+ idx = 0;
+ qreal nextPos = d->positionOfIndex(idx);
+ while ((d->isInBound(nextPos, endPos, 1.0 + 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);
if (!item) {
waiting = true;
break;
}
+ if (d->items.contains(item)) {
+ break; //Otherwise we'd "re-add" it, and get confused
+ }
if (d->currentIndex == idx) {
currentVisible = true;
- d->currentItemOffset = pos;
+ d->currentItemOffset = nextPos;
}
- if (d->items.count() == 0)
- d->firstIndex = idx;
d->items.append(item);
- d->updateItem(item, pos);
+ d->updateItem(item, nextPos);
+ endIdx = idx;
+ endPos = nextPos;
++idx;
if (idx >= d->modelCount)
idx = 0;
- pos = d->positionOfIndex(idx);
+ nextPos = d->positionOfIndex(idx);
}
- idx = d->firstIndex - 1;
+ //Prepend
+ idx = startIdx - 1;
if (idx < 0)
idx = d->modelCount - 1;
- pos = d->positionOfIndex(idx);
- while (!waiting && d->isInBound(pos, d->mappedRange - d->mappedCache, startPos) && d->items.count() < count+d->cacheSize) {
- qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
- QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0);
+ nextPos = d->positionOfIndex(idx);
+ 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);
if (!item) {
waiting = true;
break;
}
+ if (d->items.contains(item)) {
+ break; //Otherwise we'd "re-add" it, and get confused
+ }
if (d->currentIndex == idx) {
currentVisible = true;
- d->currentItemOffset = pos;
+ d->currentItemOffset = nextPos;
}
d->items.prepend(item);
- d->updateItem(item, pos);
- d->firstIndex = idx;
- idx = d->firstIndex - 1;
+ d->updateItem(item, nextPos);
+ startIdx = idx;
+ startPos = nextPos;
+ --idx;
if (idx < 0)
idx = d->modelCount - 1;
- pos = d->positionOfIndex(idx);
+ nextPos = d->positionOfIndex(idx);
+ }
+
+ // In rare cases, when jumping around with pathCount close to modelCount,
+ // new items appear in the middle. This more generic addition iteration handles this
+ // Since this is the rare case, we try append/prepend first and only do this if
+ // there are gaps still left to fill.
+ if (!waiting && d->items.count() < count+d->cacheSize) {
+ qCDebug(lcItemViewDelegateLifecycle) << "Checking for pathview middle inserts, items count was" << d->items.count();
+ idx = startIdx;
+ QQuickItem *lastItem = d->items[0];
+ while (idx != endIdx) {
+ //This gets the reference from the delegate model, and will not re-create
+ QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
+ if (!item) {
+ waiting = true;
+ break;
+ }
+ if (!d->items.contains(item)) { //We found a hole
+ nextPos = d->positionOfIndex(idx);
+ qCDebug(lcItemViewDelegateLifecycle) << "middle insert" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
+ if (d->currentIndex == idx) {
+ currentVisible = true;
+ d->currentItemOffset = nextPos;
+ }
+ int lastListIdx = d->items.indexOf(lastItem);
+ d->items.insert(lastListIdx + 1, item);
+ d->updateItem(item, nextPos);
+ }
+
+ lastItem = item;
+ ++idx;
+ if (idx >= d->modelCount)
+ idx = 0;
+ }
}
}
}
@@ -2128,7 +2186,6 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
d->offset = qmlMod(d->modelCount - d->currentIndex, d->modelCount);
changedOffset = true;
}
- d->firstIndex = -1;
d->updateMappedRange();
d->scheduleLayout();
}
@@ -2185,8 +2242,16 @@ void QQuickPathViewPrivate::createCurrentItem()
{
if (requestedIndex != -1)
return;
- int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount;
- if (itemIndex < items.count()) {
+
+ bool inItems = false;
+ for (int i = 0; i < items.count(); i++) {
+ if (model->indexOf(items[i], 0) == currentIndex) {
+ inItems = true;
+ break;
+ }
+ }
+
+ if (inItems) {
if ((currentItem = getItem(currentIndex, currentIndex))) {
currentItem->setFocus(true);
if (QQuickPathViewAttached *att = attached(currentItem))
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
index 8062e07795..0f2e4a956c 100644
--- a/src/quick/items/qquickpathview_p.h
+++ b/src/quick/items/qquickpathview_p.h
@@ -78,10 +78,6 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem
Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged)
- Q_ENUMS(HighlightRangeMode)
- Q_ENUMS(SnapMode)
- Q_ENUMS(PositionMode)
-
public:
QQuickPathView(QQuickItem *parent=0);
virtual ~QQuickPathView();
@@ -105,6 +101,7 @@ public:
QQuickItem *highlightItem();
enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ Q_ENUM(HighlightRangeMode)
HighlightRangeMode highlightRangeMode() const;
void setHighlightRangeMode(HighlightRangeMode mode);
@@ -146,10 +143,12 @@ public:
void setCacheItemCount(int);
enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
enum PositionMode { Beginning, Center, End, Contain=4, SnapPosition }; // 3 == Visible in other views
+ Q_ENUM(PositionMode)
Q_INVOKABLE void positionViewAtIndex(int index, int mode);
Q_INVOKABLE int indexAt(qreal x, qreal y) const;
Q_INVOKABLE QQuickItem *itemAt(qreal x, qreal y) const;
diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index 35ea8616a5..2a497881d4 100644
--- a/src/quick/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
@@ -155,7 +155,6 @@ public:
QQuickTimeLine tl;
QQuickTimeLineValueProxy<QQuickPathViewPrivate> moveOffset;
int flickDuration;
- int firstIndex;
int pathItems;
int requestedIndex;
int cacheSize;
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index d2de59b5d6..602b2804cc 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -42,7 +42,6 @@ class Q_AUTOTEST_EXPORT QQuickPinch : public QObject
{
Q_OBJECT
- Q_ENUMS(Axis)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget RESET resetTarget)
Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged)
Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged)
@@ -103,6 +102,7 @@ public:
}
enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
+ Q_ENUM(Axis)
Axis axis() const { return m_axis; }
void setAxis(Axis a) {
if (a == m_axis)
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
index 887d317069..de2596b679 100644
--- a/src/quick/items/qquickpositioners.cpp
+++ b/src/quick/items/qquickpositioners.cpp
@@ -70,6 +70,10 @@ QQuickBasePositioner::PositionedItem::PositionedItem(QQuickItem *i)
, index(-1)
, isNew(false)
, isVisible(true)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
{
}
@@ -116,6 +120,13 @@ void QQuickBasePositioner::PositionedItem::startTransition(QQuickItemViewTransit
transitionableItem->startTransition(transitioner, index);
}
+void QQuickBasePositioner::PositionedItem::updatePadding(qreal lp, qreal tp, qreal rp, qreal bp)
+{
+ leftPadding = lp;
+ topPadding = tp;
+ rightPadding = rp;
+ bottomPadding = bp;
+}
QQuickBasePositioner::QQuickBasePositioner(PositionerType at, QQuickItem *parent)
: QQuickImplicitSizeItem(*(new QQuickBasePositionerPrivate), parent)
@@ -388,11 +399,8 @@ void QQuickBasePositioner::prePositioning()
void QQuickBasePositioner::positionItem(qreal x, qreal y, PositionedItem *target)
{
- Q_D(QQuickBasePositioner);
- if ( (target->itemX() != x || target->itemY() != y)
- && d->type == Both) {
+ if ( target->itemX() != x || target->itemY() != y )
target->moveTo(QPointF(x, y));
- }
}
void QQuickBasePositioner::positionItemX(qreal x, PositionedItem *target)
@@ -503,6 +511,185 @@ void QQuickBasePositioner::updateAttachedProperties(QQuickPositionerAttached *sp
}
}
+qreal QQuickBasePositioner::padding() const
+{
+ Q_D(const QQuickBasePositioner);
+ return d->padding();
+}
+
+void QQuickBasePositioner::setPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ d->setPositioningDirty();
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickBasePositioner::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickBasePositioner::topPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setTopPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setTopPadding(padding);
+}
+
+void QQuickBasePositioner::resetTopPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickBasePositioner::leftPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setLeftPadding(padding);
+}
+
+void QQuickBasePositioner::resetLeftPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickBasePositioner::rightPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setRightPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setRightPadding(padding);
+}
+
+void QQuickBasePositioner::resetRightPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickBasePositioner::bottomPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setBottomPadding(padding);
+}
+
+void QQuickBasePositioner::resetBottomPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setBottomPadding(0, true);
+}
+
+QQuickBasePositionerPrivate::ExtraData::ExtraData()
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+{
+}
+
+void QQuickBasePositionerPrivate::setTopPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->topPaddingChanged();
+ }
+}
+
+void QQuickBasePositionerPrivate::setLeftPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->leftPaddingChanged();
+ }
+}
+
+void QQuickBasePositionerPrivate::setRightPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->rightPaddingChanged();
+ }
+}
+
+void QQuickBasePositionerPrivate::setBottomPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->bottomPaddingChanged();
+ }
+}
+
/*!
\qmltype Positioner
\instantiates QQuickPositionerAttached
@@ -640,6 +827,16 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
\sa Row, Grid, Flow, Positioner, ColumnLayout, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Column::padding
+ \qmlproperty real QtQuick::Column::topPadding
+ \qmlproperty real QtQuick::Column::leftPadding
+ \qmlproperty real QtQuick::Column::bottomPadding
+ \qmlproperty real QtQuick::Column::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Column::populate
This property holds the transition to be run for items that are part of
@@ -715,20 +912,23 @@ QQuickColumn::QQuickColumn(QQuickItem *parent)
void QQuickColumn::doPositioning(QSizeF *contentSize)
{
//Precondition: All items in the positioned list have a valid item pointer and should be positioned
- qreal voffset = 0;
+ qreal voffset = topPadding();
+ const qreal padding = leftPadding() + rightPadding();
+ contentSize->setWidth(qMax(contentSize->width(), padding));
for (int ii = 0; ii < positionedItems.count(); ++ii) {
PositionedItem &child = positionedItems[ii];
- positionItemY(voffset, &child);
- contentSize->setWidth(qMax(contentSize->width(), child.item->width()));
+ positionItem(child.itemX() + leftPadding() - child.leftPadding, voffset, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
+ contentSize->setWidth(qMax(contentSize->width(), child.item->width() + padding));
voffset += child.item->height();
voffset += spacing();
}
- if (voffset != 0)//If we positioned any items, undo the spacing from the last item
+ if (voffset - topPadding() != 0)//If we positioned any items, undo the spacing from the last item
voffset -= spacing();
- contentSize->setHeight(voffset);
+ contentSize->setHeight(voffset + bottomPadding());
}
void QQuickColumn::reportConflictingAnchors()
@@ -794,6 +994,16 @@ void QQuickColumn::reportConflictingAnchors()
\sa Column, Grid, Flow, Positioner, RowLayout, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Row::padding
+ \qmlproperty real QtQuick::Row::topPadding
+ \qmlproperty real QtQuick::Row::leftPadding
+ \qmlproperty real QtQuick::Row::bottomPadding
+ \qmlproperty real QtQuick::Row::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Row::populate
This property holds the transition to be run for items that are part of
@@ -940,27 +1150,34 @@ void QQuickRow::doPositioning(QSizeF *contentSize)
{
//Precondition: All items in the positioned list have a valid item pointer and should be positioned
QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this));
- qreal hoffset = 0;
+ qreal hoffset1 = leftPadding();
+ qreal hoffset2 = rightPadding();
+ if (!d->isLeftToRight())
+ qSwap(hoffset1, hoffset2);
+ qreal hoffset = hoffset1;
+ const qreal padding = topPadding() + bottomPadding();
+ contentSize->setHeight(qMax(contentSize->height(), padding));
QList<qreal> hoffsets;
for (int ii = 0; ii < positionedItems.count(); ++ii) {
PositionedItem &child = positionedItems[ii];
if (d->isLeftToRight()) {
- positionItemX(hoffset, &child);
+ positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
} else {
hoffsets << hoffset;
}
- contentSize->setHeight(qMax(contentSize->height(), child.item->height()));
+ contentSize->setHeight(qMax(contentSize->height(), child.item->height() + padding));
hoffset += child.item->width();
hoffset += spacing();
}
- if (hoffset != 0)//If we positioned any items, undo the extra spacing from the last item
+ if (hoffset - hoffset1 != 0)//If we positioned any items, undo the extra spacing from the last item
hoffset -= spacing();
- contentSize->setWidth(hoffset);
+ contentSize->setWidth(hoffset + hoffset2);
if (d->isLeftToRight())
return;
@@ -976,7 +1193,8 @@ void QQuickRow::doPositioning(QSizeF *contentSize)
for (int ii = 0; ii < positionedItems.count(); ++ii) {
PositionedItem &child = positionedItems[ii];
hoffset = end - hoffsets[acc++] - child.item->width();
- positionItemX(hoffset, &child);
+ positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
}
}
@@ -1044,6 +1262,16 @@ void QQuickRow::reportConflictingAnchors()
\sa Flow, Row, Column, Positioner, GridLayout, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Grid::padding
+ \qmlproperty real QtQuick::Grid::topPadding
+ \qmlproperty real QtQuick::Grid::leftPadding
+ \qmlproperty real QtQuick::Grid::bottomPadding
+ \qmlproperty real QtQuick::Grid::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Grid::populate
This property holds the transition to be run for items that are part of
@@ -1423,8 +1651,11 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
c = (numVisible+(m_rows-1))/m_rows;
}
- if (r == 0 || c == 0)
- return; //Nothing to do
+ if (r == 0 || c == 0) {
+ contentSize->setHeight(topPadding() + bottomPadding());
+ contentSize->setWidth(leftPadding() + rightPadding());
+ return; //Nothing else to do
+ }
QList<qreal> maxColWidth;
QList<qreal> maxRowHeight;
@@ -1476,6 +1707,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
widthSum += columnSpacing;
widthSum += maxColWidth[j];
}
+ widthSum += leftPadding() + rightPadding();
qreal heightSum = 0;
for (int i = 0; i < maxRowHeight.size(); i++) {
@@ -1483,6 +1715,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
heightSum += rowSpacing;
heightSum += maxRowHeight[i];
}
+ heightSum += topPadding() + bottomPadding();
contentSize->setHeight(heightSum);
contentSize->setWidth(widthSum);
@@ -1493,10 +1726,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
else
end = widthSum;
- qreal xoffset = 0;
+ qreal xoffset = leftPadding();
if (!d->isLeftToRight())
- xoffset = end;
- qreal yoffset = 0;
+ xoffset = end - rightPadding();
+ qreal yoffset = topPadding();
int curRow =0;
int curCol =0;
for (int i = 0; i < positionedItems.count(); ++i) {
@@ -1518,6 +1751,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
alignYOffset += maxRowHeight[curRow] - child.item->height();
positionItem(childXOffset, alignYOffset, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
if (m_flow == LeftToRight) {
if (d->isLeftToRight())
@@ -1529,9 +1763,9 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
if (!curCol) {
yoffset += maxRowHeight[curRow]+rowSpacing;
if (d->isLeftToRight())
- xoffset = 0;
+ xoffset = leftPadding();
else
- xoffset = end;
+ xoffset = end - rightPadding();
curRow++;
if (curRow>=r)
break;
@@ -1545,7 +1779,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
xoffset += maxColWidth[curCol]+columnSpacing;
else
xoffset -= maxColWidth[curCol]+columnSpacing;
- yoffset = 0;
+ yoffset = topPadding();
curCol++;
if (curCol>=c)
break;
@@ -1603,6 +1837,16 @@ void QQuickGrid::reportConflictingAnchors()
\sa Column, Row, Grid, Positioner, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Flow::padding
+ \qmlproperty real QtQuick::Flow::topPadding
+ \qmlproperty real QtQuick::Flow::leftPadding
+ \qmlproperty real QtQuick::Flow::bottomPadding
+ \qmlproperty real QtQuick::Flow::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Flow::populate
This property holds the transition to be run for items that are part of
@@ -1786,23 +2030,30 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
//Precondition: All items in the positioned list have a valid item pointer and should be positioned
Q_D(QQuickFlow);
- qreal hoffset = 0;
- qreal voffset = 0;
+ qreal hoffset1 = leftPadding();
+ qreal hoffset2 = rightPadding();
+ if (!d->isLeftToRight())
+ qSwap(hoffset1, hoffset2);
+ qreal hoffset = hoffset1;
+ const qreal voffset1 = topPadding();
+ qreal voffset = voffset1;
qreal linemax = 0;
QList<qreal> hoffsets;
+ contentSize->setWidth(qMax(contentSize->width(), hoffset1 + hoffset2));
+ contentSize->setHeight(qMax(contentSize->height(), voffset + bottomPadding()));
for (int i = 0; i < positionedItems.count(); ++i) {
PositionedItem &child = positionedItems[i];
if (d->flow == LeftToRight) {
- if (widthValid() && hoffset && hoffset + child.item->width() > width()) {
- hoffset = 0;
+ if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) {
+ hoffset = hoffset1;
voffset += linemax + spacing();
linemax = 0;
}
} else {
- if (heightValid() && voffset && voffset + child.item->height() > height()) {
- voffset = 0;
+ if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) {
+ voffset = voffset1;
hoffset += linemax + spacing();
linemax = 0;
}
@@ -1810,13 +2061,16 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
if (d->isLeftToRight()) {
positionItem(hoffset, voffset, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
} else {
hoffsets << hoffset;
positionItemY(voffset, &child);
+ child.topPadding = topPadding();
+ child.bottomPadding = bottomPadding();
}
- contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width()));
- contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height()));
+ contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2));
+ contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding()));
if (d->flow == LeftToRight) {
hoffset += child.item->width();
@@ -1828,6 +2082,7 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
linemax = qMax(linemax, child.item->width());
}
}
+
if (d->isLeftToRight())
return;
@@ -1841,6 +2096,8 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
PositionedItem &child = positionedItems[i];
hoffset = end - hoffsets[acc++] - child.item->width();
positionItemX(hoffset, &child);
+ child.leftPadding = leftPadding();
+ child.rightPadding = rightPadding();
}
}
diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h
index ea779695eb..bc67701306 100644
--- a/src/quick/items/qquickpositioners_p.h
+++ b/src/quick/items/qquickpositioners_p.h
@@ -86,6 +86,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte
Q_PROPERTY(QQuickTransition *populate READ populate WRITE setPopulate NOTIFY populateChanged)
Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged)
Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged)
+
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ 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)
public:
enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
@@ -108,6 +114,26 @@ public:
void updateAttachedProperties(QQuickPositionerAttached *specificProperty = 0, QQuickItem *specificPropertyOwner = 0) const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
protected:
QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent);
void componentComplete() Q_DECL_OVERRIDE;
@@ -120,6 +146,11 @@ Q_SIGNALS:
void populateChanged();
void moveChanged();
void addChanged();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
protected Q_SLOTS:
void prePositioning();
@@ -144,11 +175,18 @@ protected:
bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
void startTransition(QQuickItemViewTransitioner *transitioner);
+ void updatePadding(qreal lp, qreal tp, qreal rp, qreal bp);
+
QQuickItem *item;
QQuickItemViewTransitionableItem *transitionableItem;
int index;
bool isNew;
bool isVisible;
+
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
};
QPODVector<PositionedItem,8> positionedItems;
@@ -236,8 +274,8 @@ public:
void setColumnSpacing(qreal);
void resetColumnSpacing() { m_useColumnSpacing = false; }
- Q_ENUMS(Flow)
enum Flow { LeftToRight, TopToBottom };
+ Q_ENUM(Flow)
Flow flow() const;
void setFlow(Flow);
@@ -245,14 +283,14 @@ public:
void setLayoutDirection (Qt::LayoutDirection);
Qt::LayoutDirection effectiveLayoutDirection() const;
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
enum HAlignment { AlignLeft = Qt::AlignLeft,
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter};
+ Q_ENUM(HAlignment)
enum VAlignment { AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter };
+ Q_ENUM(VAlignment)
HAlignment hItemAlign() const;
void setHItemAlign(HAlignment align);
@@ -301,8 +339,8 @@ class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner
public:
QQuickFlow(QQuickItem *parent=0);
- Q_ENUMS(Flow)
enum Flow { LeftToRight, TopToBottom };
+ Q_ENUM(Flow)
Flow flow() const;
void setFlow(Flow);
diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h
index 3a8fe20351..6e1e15d4ef 100644
--- a/src/quick/items/qquickpositioners_p_p.h
+++ b/src/quick/items/qquickpositioners_p_p.h
@@ -51,6 +51,7 @@
#include <QtQuick/private/qquickstate_p.h>
#include <private/qquicktransitionmanager_p_p.h>
#include <private/qquickstatechangescript_p.h>
+#include <private/qlazilyallocated_p.h>
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
@@ -65,10 +66,26 @@ class QQuickBasePositionerPrivate : public QQuickImplicitSizeItemPrivate, public
Q_DECLARE_PUBLIC(QQuickBasePositioner)
public:
+ struct ExtraData {
+ ExtraData();
+
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
QQuickBasePositionerPrivate()
: spacing(0), type(QQuickBasePositioner::None)
, transitioner(0), positioningDirty(false)
, doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight)
+
{
}
@@ -149,6 +166,12 @@ public:
virtual void effectiveLayoutDirectionChange()
{
}
+
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index 0168d73c8f..5333ad2f08 100644
--- a/src/quick/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
@@ -50,6 +50,7 @@ QQuickRepeaterPrivate::QQuickRepeaterPrivate()
, delegateValidated(false)
, itemCount(0)
{
+ setTransparentForPositioner(true);
}
QQuickRepeaterPrivate::~QQuickRepeaterPrivate()
@@ -397,9 +398,17 @@ void QQuickRepeaterPrivate::requestItems()
void QQuickRepeater::createdItem(int index, QObject *)
{
Q_D(QQuickRepeater);
+ QObject *object = d->model->object(index, false);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ emit itemAdded(index, item);
+}
+
+void QQuickRepeater::initItem(int index, QObject *object)
+{
+ Q_D(QQuickRepeater);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+
if (!d->deletables.at(index)) {
- QObject *object = d->model->object(index, false);
- QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
if (!item) {
if (object) {
d->model->release(object);
@@ -425,17 +434,9 @@ void QQuickRepeater::createdItem(int index, QObject *)
}
item->stackBefore(after);
}
- emit itemAdded(index, item);
}
}
-void QQuickRepeater::initItem(int, QObject *object)
-{
- QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
- if (item)
- item->setParentItem(parentItem());
-}
-
void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
Q_D(QQuickRepeater);
diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h
index 7e0c021c19..b12da7a706 100644
--- a/src/quick/items/qquickscalegrid_p_p.h
+++ b/src/quick/items/qquickscalegrid_p_p.h
@@ -47,7 +47,6 @@ QT_BEGIN_NAMESPACE
class QQuickScaleGrid : public QObject
{
Q_OBJECT
- Q_ENUMS(TileRule)
Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged)
Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged)
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index 1c60d9feaa..75a8319615 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -92,8 +92,6 @@ 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 1)
- Q_ENUMS(CullMode)
- Q_ENUMS(Status)
public:
enum CullMode
@@ -102,6 +100,7 @@ public:
BackFaceCulling = QQuickShaderEffectMaterial::BackFaceCulling,
FrontFaceCulling = QQuickShaderEffectMaterial::FrontFaceCulling
};
+ Q_ENUM(CullMode)
enum Status
{
@@ -109,6 +108,7 @@ public:
Uncompiled,
Error
};
+ Q_ENUM(Status)
QQuickShaderEffect(QQuickItem *parent = 0);
~QQuickShaderEffect();
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index de6cae0ea6..b84a4adaab 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -83,7 +83,9 @@ QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickShaderEffectM
, m_compiled(false)
, m_initialized(false)
{
- for (int i = 0; i < m_attributes.count(); ++i)
+ const int attributesCount = m_attributes.count();
+ m_attributeNames.reserve(attributesCount + 1);
+ for (int i = 0; i < attributesCount; ++i)
m_attributeNames.append(m_attributes.at(i).constData());
m_attributeNames.append(0);
}
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 31e503be42..94bb315566 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -67,7 +67,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
- Q_ENUMS(Format WrapMode)
public:
enum WrapMode {
ClampToEdge,
@@ -75,12 +74,14 @@ public:
RepeatVertically,
Repeat
};
+ Q_ENUM(WrapMode)
enum Format {
Alpha = GL_ALPHA,
RGB = GL_RGB,
RGBA = GL_RGBA
};
+ Q_ENUM(Format)
QQuickShaderEffectSource(QQuickItem *parent = 0);
~QQuickShaderEffectSource();
diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp
index 579919db27..ac7fbc24af 100644
--- a/src/quick/items/qquickstateoperations.cpp
+++ b/src/quick/items/qquickstateoperations.cpp
@@ -358,7 +358,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction xa;
xa.property = property;
- xa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ xa.toBinding = newBinding;
xa.fromValue = xa.property.read();
xa.deletableToBinding = true;
actions << xa;
@@ -377,7 +377,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction ya;
ya.property = property;
- ya.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ ya.toBinding = newBinding;
ya.fromValue = ya.property.read();
ya.deletableToBinding = true;
actions << ya;
@@ -396,7 +396,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction sa;
sa.property = property;
- sa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ sa.toBinding = newBinding;
sa.fromValue = sa.property.read();
sa.deletableToBinding = true;
actions << sa;
@@ -415,7 +415,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction ra;
ra.property = property;
- ra.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ ra.toBinding = newBinding;
ra.fromValue = ra.property.read();
ra.deletableToBinding = true;
actions << ra;
@@ -434,7 +434,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction wa;
wa.property = property;
- wa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ wa.toBinding = newBinding;
wa.fromValue = wa.property.read();
wa.deletableToBinding = true;
actions << wa;
@@ -453,7 +453,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction ha;
ha.property = property;
- ha.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ ha.toBinding = newBinding;
ha.fromValue = ha.property.read();
ha.deletableToBinding = true;
actions << ha;
@@ -482,7 +482,7 @@ void QQuickParentChange::saveOriginals()
saveCurrentValues();
}*/
-void QQuickParentChange::execute(Reason)
+void QQuickParentChange::execute()
{
Q_D(QQuickParentChange);
d->doChange(d->parent);
@@ -493,7 +493,7 @@ bool QQuickParentChange::isReversable()
return true;
}
-void QQuickParentChange::reverse(Reason)
+void QQuickParentChange::reverse()
{
Q_D(QQuickParentChange);
d->doChange(d->origParent, d->origStackBefore);
@@ -765,12 +765,7 @@ class QQuickAnchorChangesPrivate : public QQuickStateOperationPrivate
{
public:
QQuickAnchorChangesPrivate()
- : target(0), anchorSet(new QQuickAnchorSet),
- leftBinding(0), rightBinding(0), hCenterBinding(0),
- topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0),
- origLeftBinding(0), origRightBinding(0), origHCenterBinding(0),
- origTopBinding(0), origBottomBinding(0), origVCenterBinding(0),
- origBaselineBinding(0)
+ : target(0), anchorSet(new QQuickAnchorSet)
{
}
@@ -779,21 +774,21 @@ public:
QQuickItem *target;
QQuickAnchorSet *anchorSet;
- QQmlBinding *leftBinding;
- QQmlBinding *rightBinding;
- QQmlBinding *hCenterBinding;
- QQmlBinding *topBinding;
- QQmlBinding *bottomBinding;
- QQmlBinding *vCenterBinding;
- QQmlBinding *baselineBinding;
-
- QQmlAbstractBinding *origLeftBinding;
- QQmlAbstractBinding *origRightBinding;
- QQmlAbstractBinding *origHCenterBinding;
- QQmlAbstractBinding *origTopBinding;
- QQmlAbstractBinding *origBottomBinding;
- QQmlAbstractBinding *origVCenterBinding;
- QQmlAbstractBinding *origBaselineBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> leftBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> rightBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> hCenterBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> topBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> bottomBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> vCenterBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> baselineBinding;
+
+ QQmlAbstractBinding::Ptr origLeftBinding;
+ QQmlAbstractBinding::Ptr origRightBinding;
+ QQmlAbstractBinding::Ptr origHCenterBinding;
+ QQmlAbstractBinding::Ptr origTopBinding;
+ QQmlAbstractBinding::Ptr origBottomBinding;
+ QQmlAbstractBinding::Ptr origVCenterBinding;
+ QQmlAbstractBinding::Ptr origBaselineBinding;
QQuickAnchorLine rewindLeft;
QQuickAnchorLine rewindRight;
@@ -831,8 +826,6 @@ public:
qreal origX;
qreal origY;
- QList<QQmlAbstractBinding*> oldBindings;
-
QQmlProperty leftProp;
QQmlProperty rightProp;
QQmlProperty hCenterProp;
@@ -849,29 +842,6 @@ QQuickAnchorChanges::QQuickAnchorChanges(QObject *parent)
QQuickAnchorChanges::~QQuickAnchorChanges()
{
- /*
- if the anchorchanges is active at destruction, any non-active orig
- bindings need to be destroyed
-
- the basic logic is that if both e.g. left and origLeft are present,
- then we are active (otherwise left would have been destroyed), and
- left is in use and origLeft needs to be cleaned up.
- */
- Q_D(QQuickAnchorChanges);
- if (d->leftBinding && d->origLeftBinding)
- d->origLeftBinding->destroy();
- if (d->rightBinding && d->origRightBinding)
- d->origRightBinding->destroy();
- if (d->hCenterBinding && d->origHCenterBinding)
- d->origHCenterBinding->destroy();
- if (d->topBinding && d->origTopBinding)
- d->origTopBinding->destroy();
- if (d->bottomBinding && d->origBottomBinding)
- d->origBottomBinding->destroy();
- if (d->vCenterBinding && d->origVCenterBinding)
- d->origVCenterBinding->destroy();
- if (d->baselineBinding && d->origBaselineBinding)
- d->origBaselineBinding->destroy();
}
QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions()
@@ -967,7 +937,7 @@ void QQuickAnchorChanges::setObject(QQuickItem *target)
\endqml
*/
-void QQuickAnchorChanges::execute(Reason reason)
+void QQuickAnchorChanges::execute()
{
Q_D(QQuickAnchorChanges);
if (!d->target)
@@ -978,94 +948,84 @@ void QQuickAnchorChanges::execute(Reason reason)
if (d->applyOrigLeft) {
if (!d->origLeftBinding)
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
+ QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
}
if (d->applyOrigRight) {
if (!d->origRightBinding)
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
+ QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
}
if (d->applyOrigHCenter) {
if (!d->origHCenterBinding)
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
}
if (d->applyOrigTop) {
if (!d->origTopBinding)
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding);
+ QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
}
if (d->applyOrigBottom) {
if (!d->origBottomBinding)
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
+ QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
}
if (d->applyOrigVCenter) {
if (!d->origVCenterBinding)
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
}
if (d->applyOrigBaseline) {
if (!d->origBaselineBinding)
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
- }
-
- //destroy old bindings
- if (reason == ActualChange) {
- for (int i = 0; i < d->oldBindings.size(); ++i) {
- QQmlAbstractBinding *binding = d->oldBindings.at(i);
- if (binding)
- binding->destroy();
- }
- d->oldBindings.clear();
+ QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
}
//reset any anchors that have been specified as "undefined"
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::LeftAnchor) {
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->leftProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) {
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->rightProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) {
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->hCenterProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) {
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->topProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) {
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->bottomProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) {
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->vCenterProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) {
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->baselineProp);
}
//set any anchors that have been specified
if (d->leftBinding)
- QQmlPropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding);
+ QQmlPropertyPrivate::setBinding(d->leftBinding.data());
if (d->rightBinding)
- QQmlPropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding);
+ QQmlPropertyPrivate::setBinding(d->rightBinding.data());
if (d->hCenterBinding)
- QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->hCenterBinding.data());
if (d->topBinding)
- QQmlPropertyPrivate::setBinding(d->topBinding->property(), d->topBinding);
+ QQmlPropertyPrivate::setBinding(d->topBinding.data());
if (d->bottomBinding)
- QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding);
+ QQmlPropertyPrivate::setBinding(d->bottomBinding.data());
if (d->vCenterBinding)
- QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->vCenterBinding.data());
if (d->baselineBinding)
- QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding);
+ QQmlPropertyPrivate::setBinding(d->baselineBinding.data());
}
bool QQuickAnchorChanges::isReversable()
@@ -1073,7 +1033,7 @@ bool QQuickAnchorChanges::isReversable()
return true;
}
-void QQuickAnchorChanges::reverse(Reason reason)
+void QQuickAnchorChanges::reverse()
{
Q_D(QQuickAnchorChanges);
if (!d->target)
@@ -1083,69 +1043,48 @@ void QQuickAnchorChanges::reverse(Reason reason)
//reset any anchors set by the state
if (d->leftBinding) {
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftBinding->property(), 0);
- if (reason == ActualChange) {
- d->leftBinding->destroy(); d->leftBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->leftBinding.data());
}
if (d->rightBinding) {
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightBinding->property(), 0);
- if (reason == ActualChange) {
- d->rightBinding->destroy(); d->rightBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->rightBinding.data());
}
if (d->hCenterBinding) {
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), 0);
- if (reason == ActualChange) {
- d->hCenterBinding->destroy(); d->hCenterBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->hCenterBinding.data());
}
if (d->topBinding) {
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topBinding->property(), 0);
- if (reason == ActualChange) {
- d->topBinding->destroy(); d->topBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->topBinding.data());
}
if (d->bottomBinding) {
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), 0);
- if (reason == ActualChange) {
- d->bottomBinding->destroy(); d->bottomBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->bottomBinding.data());
}
if (d->vCenterBinding) {
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), 0);
- if (reason == ActualChange) {
- d->vCenterBinding->destroy(); d->vCenterBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->vCenterBinding.data());
}
if (d->baselineBinding) {
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), 0);
- if (reason == ActualChange) {
- d->baselineBinding->destroy(); d->baselineBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->baselineBinding.data());
}
//restore previous anchors
if (d->origLeftBinding)
- QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
+ QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
if (d->origRightBinding)
- QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
+ QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
if (d->origHCenterBinding)
- QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
if (d->origTopBinding)
- QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding);
+ QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
if (d->origBottomBinding)
- QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
+ QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
if (d->origVCenterBinding)
- QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
if (d->origBaselineBinding)
- QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
+ QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
//restore any absolute geometry changed by the state's anchors
QQuickAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Vertical_Mask;
@@ -1289,10 +1228,6 @@ void QQuickAnchorChanges::copyOriginals(QQuickStateActionEvent *other)
d->origX = acp->origX;
d->origY = acp->origY;
- d->oldBindings.clear();
- d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
- << acp->topBinding << acp->bottomBinding << acp->vCenterBinding << acp->baselineBinding;
-
//clear old values from other
//### could this be generalized for all QQuickStateActionEvents, and called after copyOriginals?
acp->leftBinding = 0;
@@ -1333,31 +1268,31 @@ void QQuickAnchorChanges::clearBindings()
d->anchorSet->d_func()->usedAnchors;
if (d->applyOrigLeft || (combined & QQuickAnchors::LeftAnchor)) {
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->leftProp);
}
if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) {
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->rightProp);
}
if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) {
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->hCenterProp);
}
if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) {
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->topProp);
}
if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) {
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->bottomProp);
}
if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) {
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->vCenterProp);
}
if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) {
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->baselineProp);
}
}
diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h
index 8d4231c5fa..1999e23a83 100644
--- a/src/quick/items/qquickstateoperations_p.h
+++ b/src/quick/items/qquickstateoperations_p.h
@@ -97,9 +97,9 @@ public:
void saveOriginals() Q_DECL_OVERRIDE;
//virtual void copyOriginals(QQuickStateActionEvent*);
- void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void execute() Q_DECL_OVERRIDE;
bool isReversable() Q_DECL_OVERRIDE;
- void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void reverse() Q_DECL_OVERRIDE;
EventType type() const Q_DECL_OVERRIDE;
bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE;
void rewind() Q_DECL_OVERRIDE;
@@ -180,9 +180,9 @@ public:
QQuickItem *object() const;
void setObject(QQuickItem *);
- void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void execute() Q_DECL_OVERRIDE;
bool isReversable() Q_DECL_OVERRIDE;
- void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void reverse() Q_DECL_OVERRIDE;
EventType type() const Q_DECL_OVERRIDE;
bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE;
bool changesBindings() Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index dd4f57bfdb..2475d19c8d 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -85,7 +85,16 @@ QQuickTextPrivate::QQuickTextPrivate()
}
QQuickTextPrivate::ExtraData::ExtraData()
- : lineHeight(1.0)
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+ , lineHeight(1.0)
, doc(0)
, minimumPixelSize(12)
, minimumPointSize(12)
@@ -283,6 +292,74 @@ qreal QQuickTextPrivate::getImplicitHeight() const
return implicitHeight;
}
+qreal QQuickTextPrivate::availableWidth() const
+{
+ Q_Q(const QQuickText);
+ return q->width() - q->leftPadding() - q->rightPadding();
+}
+
+qreal QQuickTextPrivate::availableHeight() const
+{
+ Q_Q(const QQuickText);
+ return q->height() - q->topPadding() - q->bottomPadding();
+}
+
+void QQuickTextPrivate::setTopPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickText);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->topPaddingChanged();
+ }
+}
+
+void QQuickTextPrivate::setLeftPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickText);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->leftPaddingChanged();
+ }
+}
+
+void QQuickTextPrivate::setRightPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickText);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->rightPaddingChanged();
+ }
+}
+
+void QQuickTextPrivate::setBottomPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickText);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->bottomPaddingChanged();
+ }
+}
+
/*!
\qmlproperty bool QtQuick::Text::antialiasing
@@ -326,9 +403,9 @@ void QQuickTextPrivate::updateLayout()
formatModifiesFontSize = fontSizeModified;
multilengthEos = -1;
} else {
- layout.clearAdditionalFormats();
+ layout.clearFormats();
if (elideLayout)
- elideLayout->clearAdditionalFormats();
+ elideLayout->clearFormats();
QString tmp = text;
multilengthEos = tmp.indexOf(QLatin1Char('\x9c'));
if (multilengthEos != -1) {
@@ -409,7 +486,7 @@ void QQuickTextPrivate::updateBaseline(qreal baseline, qreal dy)
yoff = dy/2;
}
- q->setBaselineOffset(baseline + yoff);
+ q->setBaselineOffset(baseline + yoff + q->topPadding());
}
void QQuickTextPrivate::updateSize()
@@ -429,6 +506,9 @@ void QQuickTextPrivate::updateSize()
return;
}
+ qreal hPadding = q->leftPadding() + q->rightPadding();
+ qreal vPadding = q->topPadding() + q->bottomPadding();
+
if (text.isEmpty() && !isLineLaidOutConnected() && fontSizeMode() == QQuickText::FixedSize) {
// How much more expensive is it to just do a full layout on an empty string here?
// There may be subtle differences in the height and baseline calculations between
@@ -441,8 +521,8 @@ void QQuickTextPrivate::updateSize()
? lineHeight()
: fontHeight * lineHeight();
}
- updateBaseline(fm.ascent(), q->height() - fontHeight);
- q->setImplicitSize(0, fontHeight);
+ updateBaseline(fm.ascent(), q->height() - fontHeight - vPadding);
+ q->setImplicitSize(hPadding, fontHeight + vPadding);
layedOutTextRect = QRectF(0, 0, 0, fontHeight);
emit q->contentSizeChanged();
updateType = UpdatePaintNode;
@@ -463,7 +543,7 @@ void QQuickTextPrivate::updateSize()
layedOutTextRect = textRect;
size = textRect.size();
- updateBaseline(baseline, q->height() - size.height());
+ updateBaseline(baseline, q->height() - size.height() - vPadding);
} else {
widthExceeded = true; // always relayout rich text on width changes..
heightExceeded = false; // rich text layout isn't affected by height changes.
@@ -487,15 +567,15 @@ void QQuickTextPrivate::updateSize()
naturalWidth = extra->doc->idealWidth();
const bool wasInLayout = internalWidthUpdate;
internalWidthUpdate = true;
- q->setImplicitWidth(naturalWidth);
+ q->setImplicitWidth(naturalWidth + hPadding);
internalWidthUpdate = wasInLayout;
}
if (internalWidthUpdate)
return;
extra->doc->setPageSize(QSizeF());
- if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < q->width()))
- extra->doc->setTextWidth(q->width());
+ if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < availableWidth()))
+ extra->doc->setTextWidth(availableWidth());
else
extra->doc->setTextWidth(extra->doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
@@ -504,7 +584,7 @@ void QQuickTextPrivate::updateSize()
size = QSizeF(extra->doc->idealWidth(),dsize.height());
QFontMetricsF fm(font);
- updateBaseline(fm.ascent(), q->height() - size.height());
+ updateBaseline(fm.ascent(), q->height() - size.height() - vPadding);
//### need to confirm cost of always setting these for richText
internalWidthUpdate = true;
@@ -512,11 +592,11 @@ void QQuickTextPrivate::updateSize()
if (!q->widthValid())
iWidth = size.width();
if (iWidth > -1)
- q->setImplicitSize(iWidth, size.height());
+ q->setImplicitSize(iWidth + hPadding, size.height() + vPadding);
internalWidthUpdate = false;
if (iWidth == -1)
- q->setImplicitHeight(size.height());
+ q->setImplicitHeight(size.height() + vPadding);
}
if (layedOutTextRect.size() != previousSize)
@@ -622,7 +702,7 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height,
// use the text item's width by default if it has one and wrap is on or text must be aligned
if (q->widthValid() && (q->wrapMode() != QQuickText::NoWrap ||
q->effectiveHAlign() != QQuickText::AlignLeft))
- textLine->setWidth(q->width());
+ textLine->setWidth(availableWidth());
else
textLine->setWidth(INT_MAX);
if (lineHeight() != 1.0)
@@ -634,10 +714,10 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height,
}
void QQuickTextPrivate::elideFormats(
- const int start, const int length, int offset, QList<QTextLayout::FormatRange> *elidedFormats)
+ const int start, const int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats)
{
const int end = start + length;
- QList<QTextLayout::FormatRange> formats = layout.additionalFormats();
+ const QVector<QTextLayout::FormatRange> formats = layout.formats();
for (int i = 0; i < formats.count(); ++i) {
QTextLayout::FormatRange format = formats.at(i);
const int formatLength = qMin(format.start + format.length, end) - qMax(format.start, start);
@@ -690,10 +770,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
&& (q->heightValid() || maximumLineCountValid);
if ((!requireImplicitSize || (implicitWidthValid && implicitHeightValid))
- && ((singlelineElide && q->width() <= 0.) || (multilineElide && q->heightValid() && q->height() <= 0.))) {
+ && ((singlelineElide && availableWidth() <= 0.)
+ || (multilineElide && q->heightValid() && availableHeight() <= 0.))) {
// we are elided and we have a zero width or height
- widthExceeded = q->widthValid() && q->width() <= 0.;
- heightExceeded = q->heightValid() && q->height() <= 0.;
+ widthExceeded = q->widthValid() && availableWidth() <= 0.;
+ heightExceeded = q->heightValid() && availableHeight() <= 0.;
if (!truncated) {
truncated = true;
@@ -729,7 +810,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
lineWidth = (q->widthValid() || implicitWidthValid) && q->width() > 0
? q->width()
: FLT_MAX;
- qreal maxHeight = q->heightValid() ? q->height() : FLT_MAX;
+ qreal maxHeight = q->heightValid() ? availableHeight() : FLT_MAX;
const bool customLayout = isLineLaidOutConnected();
const bool wasTruncated = truncated;
@@ -750,8 +831,8 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
int scaledFontSize = largeFont;
bool widthChanged = false;
- widthExceeded = q->width() <= 0 && (singlelineElide || canWrap || horizontalFit);
- heightExceeded = q->height() <= 0 && (multilineElide || verticalFit);
+ widthExceeded = availableWidth() <= 0 && (singlelineElide || canWrap || horizontalFit);
+ heightExceeded = availableHeight() <= 0 && (multilineElide || verticalFit);
QRectF br;
@@ -921,7 +1002,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
bool wasInLayout = internalWidthUpdate;
internalWidthUpdate = true;
- q->setImplicitSize(naturalWidth, naturalHeight);
+ q->setImplicitSize(naturalWidth + q->leftPadding() + q->rightPadding(), naturalHeight + q->topPadding() + q->bottomPadding());
internalWidthUpdate = wasInLayout;
// Update any variables that are dependent on the validity of the width or height.
@@ -938,8 +1019,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
const qreal oldWidth = lineWidth;
const qreal oldHeight = maxHeight;
- lineWidth = q->widthValid() && q->width() > 0 ? q->width() : naturalWidth;
- maxHeight = q->heightValid() ? q->height() : FLT_MAX;
+ const qreal availWidth = availableWidth();
+ const qreal availHeight = availableHeight();
+
+ lineWidth = q->widthValid() && availWidth > 0 ? availWidth : naturalWidth;
+ maxHeight = q->heightValid() ? availHeight : FLT_MAX;
// If the width of the item has changed and it's possible the result of wrapping,
// eliding, scaling has changed, or the text is not left aligned do another layout.
@@ -992,7 +1076,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
&& (q->heightValid() || (maximumLineCountValid && canWrap));
const qreal oldHeight = maxHeight;
- maxHeight = q->heightValid() ? q->height() : FLT_MAX;
+ maxHeight = q->heightValid() ? availableHeight() : FLT_MAX;
// If the height of the item has changed and it's possible the result of eliding,
// line count truncation or scaling has changed, do another layout.
if ((maxHeight < qMin(oldHeight, naturalHeight) || (heightExceeded && maxHeight > oldHeight))
@@ -1072,7 +1156,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
elideLayout->setCacheEnabled(true);
}
if (styledText) {
- QList<QTextLayout::FormatRange> formats;
+ QVector<QTextLayout::FormatRange> formats;
switch (elideMode) {
case QQuickText::ElideRight:
elideFormats(elideStart, elideText.length() - 1, 0, &formats);
@@ -1095,7 +1179,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
default:
break;
}
- elideLayout->setAdditionalFormats(formats);
+ elideLayout->setFormats(formats);
}
elideLayout->setFont(layout.font());
@@ -2278,7 +2362,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
d->updateType = QQuickTextPrivate::UpdateNone;
- const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), height(), d->vAlign);
+ const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), d->availableHeight(), d->vAlign) + topPadding();
QQuickTextNode *node = 0;
if (!oldNode)
@@ -2295,11 +2379,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
const QColor linkColor = QColor::fromRgba(d->linkColor);
if (d->richText) {
- const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), effectiveHAlign());
+ const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), d->availableWidth(), effectiveHAlign()) + leftPadding();
d->ensureDoc();
node->addTextDocument(QPointF(dx, dy), d->extra->doc, color, d->style, styleColor, linkColor);
} else if (d->layedOutTextRect.width() > 0) {
- const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), effectiveHAlign());
+ const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, d->availableWidth(), effectiveHAlign()) + leftPadding();
int unelidedLineCount = d->lineCount;
if (d->elideLayout)
unelidedLineCount -= 1;
@@ -2567,7 +2651,7 @@ QString QQuickTextPrivate::anchorAt(const QTextLayout *layout, const QPointF &mo
QTextLine line = layout->lineAt(i);
if (line.naturalTextRect().contains(mousePos)) {
int charPos = line.xToCursor(mousePos.x(), QTextLine::CursorOnCharacter);
- foreach (const QTextLayout::FormatRange &formatRange, layout->additionalFormats()) {
+ foreach (const QTextLayout::FormatRange &formatRange, layout->formats()) {
if (formatRange.format.isAnchor()
&& charPos >= formatRange.start
&& charPos < formatRange.start + formatRange.length) {
@@ -2584,14 +2668,15 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) const
{
Q_Q(const QQuickText);
QPointF translatedMousePos = mousePos;
- translatedMousePos.ry() -= QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), q->height(), vAlign);
+ translatedMousePos.rx() -= q->leftPadding();
+ translatedMousePos.ry() -= q->topPadding() + QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), availableHeight(), vAlign);
if (styledText) {
QString link = anchorAt(&layout, translatedMousePos);
if (link.isEmpty() && elideLayout)
link = anchorAt(elideLayout, translatedMousePos);
return link;
} else if (richText && extra.isAllocated() && extra->doc) {
- translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), q->effectiveHAlign());
+ translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), availableWidth(), q->effectiveHAlign());
return extra->doc->documentLayout()->anchorAt(translatedMousePos);
}
return QString();
@@ -2809,4 +2894,125 @@ void QQuickText::invalidateFontCaches()
}
}
+/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Text::padding
+ \qmlproperty real QtQuick::Text::topPadding
+ \qmlproperty real QtQuick::Text::leftPadding
+ \qmlproperty real QtQuick::Text::bottomPadding
+ \qmlproperty real QtQuick::Text::rightPadding
+
+ These properties hold the padding around the content. This space is reserved
+ in addition to the contentWidth and contentHeight.
+*/
+qreal QQuickText::padding() const
+{
+ Q_D(const QQuickText);
+ return d->padding();
+}
+
+void QQuickText::setPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ d->updateSize();
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickText::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickText::topPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickText::setTopPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setTopPadding(padding);
+}
+
+void QQuickText::resetTopPadding()
+{
+ Q_D(QQuickText);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickText::leftPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickText::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setLeftPadding(padding);
+}
+
+void QQuickText::resetLeftPadding()
+{
+ Q_D(QQuickText);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickText::rightPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickText::setRightPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setRightPadding(padding);
+}
+
+void QQuickText::resetRightPadding()
+{
+ Q_D(QQuickText);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickText::bottomPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickText::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setBottomPadding(padding);
+}
+
+void QQuickText::resetBottomPadding()
+{
+ Q_D(QQuickText);
+ d->setBottomPadding(0, true);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index 283e3b510b..f92927c9c4 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -45,15 +45,6 @@ class QQuickTextLine;
class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
- Q_ENUMS(TextStyle)
- Q_ENUMS(TextFormat)
- Q_ENUMS(TextElideMode)
- Q_ENUMS(WrapMode)
- Q_ENUMS(LineHeightMode)
- Q_ENUMS(FontSizeMode)
- Q_ENUMS(RenderType)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
@@ -84,6 +75,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2)
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ 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)
+
public:
QQuickText(QQuickItem *parent=0);
~QQuickText();
@@ -92,21 +89,26 @@ public:
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter,
AlignJustify = Qt::AlignJustify };
+ Q_ENUM(HAlignment)
enum VAlignment { AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter };
+ Q_ENUM(VAlignment)
enum TextStyle { Normal,
Outline,
Raised,
Sunken };
+ Q_ENUM(TextStyle)
enum TextFormat { PlainText = Qt::PlainText,
RichText = Qt::RichText,
AutoText = Qt::AutoText,
StyledText = 4 };
+ Q_ENUM(TextFormat)
enum TextElideMode { ElideLeft = Qt::ElideLeft,
ElideRight = Qt::ElideRight,
ElideMiddle = Qt::ElideMiddle,
ElideNone = Qt::ElideNone };
+ Q_ENUM(TextElideMode)
enum WrapMode { NoWrap = QTextOption::NoWrap,
WordWrap = QTextOption::WordWrap,
@@ -114,15 +116,19 @@ public:
WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
};
+ Q_ENUM(WrapMode)
enum RenderType { QtRendering,
NativeRendering
};
+ Q_ENUM(RenderType)
enum LineHeightMode { ProportionalHeight, FixedHeight };
+ Q_ENUM(LineHeightMode)
enum FontSizeMode { FixedSize = 0x0, HorizontalFit = 0x01, VerticalFit = 0x02,
Fit = HorizontalFit | VerticalFit };
+ Q_ENUM(FontSizeMode)
QString text() const;
void setText(const QString &);
@@ -204,6 +210,26 @@ public:
Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
Q_SIGNALS:
void textChanged(const QString &text);
void linkActivated(const QString &link);
@@ -231,6 +257,11 @@ Q_SIGNALS:
void lineLaidOut(QQuickTextLine *line);
void baseUrlChanged();
void renderTypeChanged();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 9a6da3736e..f0469fc8ea 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -78,7 +78,7 @@ public:
int lineHeightOffset() const;
QString elidedText(qreal lineWidth, const QTextLine &line, QTextLine *nextLine = 0) const;
- void elideFormats(int start, int length, int offset, QList<QTextLayout::FormatRange> *elidedFormats);
+ void elideFormats(int start, int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats);
void processHoverEvent(QHoverEvent *event);
@@ -87,6 +87,15 @@ public:
struct ExtraData {
ExtraData();
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
qreal lineHeight;
QQuickTextDocumentWithImageResources *doc;
QString activeLink;
@@ -159,6 +168,15 @@ public:
qreal getImplicitWidth() const Q_DECL_OVERRIDE;
qreal getImplicitHeight() const Q_DECL_OVERRIDE;
+ qreal availableWidth() const;
+ qreal availableHeight() const;
+
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
+
void ensureDoc();
QRectF setupTextLayout(qreal * const baseline);
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 95d2e7c995..19cdc388f1 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -1313,7 +1313,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
QTextLayout *layout = block.layout();
if (isGettingInput)
layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
- QList<QTextLayout::FormatRange> overrides;
+ QVector<QTextLayout::FormatRange> overrides;
const int oldPreeditCursor = preeditCursor;
preeditCursor = e->preeditString().length();
hasImState = !e->preeditString().isEmpty();
@@ -1336,7 +1336,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
}
}
}
- layout->setAdditionalFormats(overrides);
+ layout->setFormats(overrides);
cursor.endEditBlock();
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 8237ad10e4..2887dad8ce 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -172,6 +172,13 @@ QQuickTextEdit::QQuickTextEdit(QQuickItem *parent)
d->init();
}
+QQuickTextEdit::QQuickTextEdit(QQuickTextEditPrivate &dd, QQuickItem *parent)
+: QQuickImplicitSizeItem(dd, parent)
+{
+ Q_D(QQuickTextEdit);
+ d->init();
+}
+
QString QQuickTextEdit::text() const
{
Q_D(const QQuickTextEdit);
@@ -699,6 +706,62 @@ Qt::InputMethodHints QQuickTextEditPrivate::effectiveInputMethodHints() const
}
#endif
+void QQuickTextEditPrivate::setTopPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->topPaddingChanged();
+ }
+}
+
+void QQuickTextEditPrivate::setLeftPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->leftPaddingChanged();
+ }
+}
+
+void QQuickTextEditPrivate::setRightPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->rightPaddingChanged();
+ }
+}
+
+void QQuickTextEditPrivate::setBottomPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->bottomPaddingChanged();
+ }
+}
+
QQuickTextEdit::VAlignment QQuickTextEdit::vAlign() const
{
Q_D(const QQuickTextEdit);
@@ -1658,6 +1721,8 @@ void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
#ifndef QT_NO_IM
if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
qGuiApp->inputMethod()->show();
+#else
+ Q_UNUSED(hadActiveFocus);
#endif
}
if (!event->isAccepted())
@@ -1793,6 +1858,14 @@ void QQuickTextEdit::invalidateFontCaches()
}
}
+inline void resetEngine(QQuickTextNodeEngine *engine, const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor)
+{
+ *engine = QQuickTextNodeEngine();
+ engine->setTextColor(textColor);
+ engine->setSelectedTextColor(selectedTextColor);
+ engine->setSelectionColor(selectionColor);
+}
+
QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
{
Q_UNUSED(updatePaintNodeData);
@@ -1818,6 +1891,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
while (nodeIterator != d->textNodeMap.end() && !(*nodeIterator)->dirty())
++nodeIterator;
+ QQuickTextNodeEngine engine;
+ QQuickTextNodeEngine frameDecorationsEngine;
if (!oldNode || nodeIterator < d->textNodeMap.end()) {
@@ -1837,6 +1912,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
// FIXME: the text decorations could probably be handled separately (only updated for affected textFrames)
rootNode->resetFrameDecorations(d->createTextNode());
+ resetEngine(&frameDecorationsEngine, d->color, d->selectedTextColor, d->selectionColor);
QQuickTextNode *node = 0;
@@ -1856,11 +1932,12 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
while (!frames.isEmpty()) {
QTextFrame *textFrame = frames.takeFirst();
frames.append(textFrame->childFrames());
- rootNode->frameDecorationsNode->m_engine->addFrameDecorations(d->document, textFrame);
+ frameDecorationsEngine.addFrameDecorations(d->document, textFrame);
if (textFrame->lastPosition() < firstDirtyPos || (firstCleanNode && textFrame->firstPosition() >= firstCleanNode->startPos()))
continue;
node = d->createTextNode();
+ resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
if (textFrame->firstPosition() > textFrame->lastPosition()
&& textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
@@ -1869,8 +1946,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
ProtectedLayoutAccessor *a = static_cast<ProtectedLayoutAccessor *>(d->document->documentLayout());
QTextCharFormat format = a->formatAccessor(pos);
QTextBlock block = textFrame->firstCursorPosition().block();
- node->m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- node->m_engine->addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
+ engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
+ engine.addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
pos, textFrame->frameFormat().position());
nodeStart = pos;
} else if (qobject_cast<QTextTable*>(textFrame)) { // To keep things simple, map text tables as one text node
@@ -1878,7 +1955,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
nodeOffset = d->document->documentLayout()->frameBoundingRect(textFrame).topLeft();
updateNodeTransform(node, nodeOffset);
while (!it.atEnd())
- node->m_engine->addTextBlock(d->document, (it++).currentBlock(), -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
+ engine.addTextBlock(d->document, (it++).currentBlock(), -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
nodeStart = textFrame->firstPosition();
} else {
// Having nodes spanning across frame boundaries will break the current bookkeeping mechanism. We need to prevent that.
@@ -1895,13 +1972,13 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
if (block.position() < firstDirtyPos)
continue;
- if (!node->m_engine->hasContents()) {
+ if (!engine.hasContents()) {
nodeOffset = d->document->documentLayout()->blockBoundingRect(block).topLeft();
updateNodeTransform(node, nodeOffset);
nodeStart = block.position();
}
- node->m_engine->addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
+ engine.addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
currentNodeSize += block.length();
if ((it.atEnd()) || (firstCleanNode && block.next().position() >= firstCleanNode->startPos())) // last node that needed replacing or last block of the frame
@@ -1910,15 +1987,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
QList<int>::const_iterator lowerBound = std::lower_bound(frameBoundaries.constBegin(), frameBoundaries.constEnd(), block.next().position());
if (currentNodeSize > nodeBreakingSize || lowerBound == frameBoundaries.constEnd() || *lowerBound > nodeStart) {
currentNodeSize = 0;
- d->addCurrentTextNodeToRoot(rootNode, node, nodeIterator, nodeStart);
+ d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
node = d->createTextNode();
+ resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
nodeStart = block.next().position();
}
}
}
- d->addCurrentTextNodeToRoot(rootNode, node, nodeIterator, nodeStart);
+ d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
}
- rootNode->frameDecorationsNode->m_engine->addToSceneGraph(rootNode->frameDecorationsNode, QQuickText::Normal, QColor());
+ frameDecorationsEngine.addToSceneGraph(rootNode->frameDecorationsNode, QQuickText::Normal, QColor());
// Now prepend the frame decorations since we want them rendered first, with the text nodes and cursor in front.
rootNode->prependChildNode(rootNode->frameDecorationsNode);
@@ -2023,6 +2101,19 @@ bool QQuickTextEdit::isInputMethodComposing() const
#endif // QT_NO_IM
}
+QQuickTextEditPrivate::ExtraData::ExtraData()
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+{
+}
+
void QQuickTextEditPrivate::init()
{
Q_Q(QQuickTextEdit);
@@ -2106,7 +2197,7 @@ void QQuickTextEdit::markDirtyNodesForRange(int start, int end, int charDelta)
}
// mark the affected nodes as dirty
- while (it != d->textNodeMap.constEnd()) {
+ while (it != d->textNodeMap.end()) {
if ((*it)->startPos() <= end)
(*it)->setDirty();
else if (charDelta)
@@ -2232,7 +2323,7 @@ void QQuickTextEdit::updateSize()
return;
}
- qreal naturalWidth = d->implicitWidth;
+ qreal naturalWidth = d->implicitWidth - leftPadding() - rightPadding();
qreal newWidth = d->document->idealWidth();
// ### assumes that if the width is set, the text will fill to edges
@@ -2250,13 +2341,13 @@ void QQuickTextEdit::updateSize()
const bool wasInLayout = d->inLayout;
d->inLayout = true;
- setImplicitWidth(naturalWidth);
+ setImplicitWidth(naturalWidth + leftPadding() + rightPadding());
d->inLayout = wasInLayout;
if (d->inLayout) // probably the result of a binding loop, but by letting it
return; // get this far we'll get a warning to that effect.
}
if (d->document->textWidth() != width()) {
- d->document->setTextWidth(width());
+ d->document->setTextWidth(width() - leftPadding() - rightPadding());
newWidth = d->document->idealWidth();
}
//### need to confirm cost of always setting these
@@ -2271,12 +2362,12 @@ void QQuickTextEdit::updateSize()
// ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
if (!widthValid() && !d->requireImplicitWidth)
- setImplicitSize(newWidth, newHeight);
+ setImplicitSize(newWidth + leftPadding() + rightPadding(), newHeight + topPadding() + bottomPadding());
else
- setImplicitHeight(newHeight);
+ setImplicitHeight(newHeight + topPadding() + bottomPadding());
- d->xoff = qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign()));
- d->yoff = QQuickTextUtil::alignedY(d->document->size().height(), height(), d->vAlign);
+ d->xoff = leftPadding() + qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width() - leftPadding() - rightPadding(), effectiveHAlign()));
+ d->yoff = topPadding() + QQuickTextUtil::alignedY(d->document->size().height(), height() - topPadding() - bottomPadding(), d->vAlign);
setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
QSizeF size(newWidth, newHeight);
@@ -2423,16 +2514,19 @@ void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event)
qGuiApp->inputMethod()->show();
q->connect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
q, SLOT(q_updateAlignment()));
+#endif
} else {
+#ifndef QT_NO_IM
q->disconnect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
q, SLOT(q_updateAlignment()));
#endif
+ emit q->editingFinished();
}
}
-void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QSGTransformNode *root, QQuickTextNode *node, TextNodeIterator &it, int startPos)
+void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QQuickTextNodeEngine *engine, QSGTransformNode *root, QQuickTextNode *node, TextNodeIterator &it, int startPos)
{
- node->m_engine->addToSceneGraph(node, QQuickText::Normal, QColor());
+ engine->addToSceneGraph(node, QQuickText::Normal, QColor());
it = textNodeMap.insert(it, new TextNode(startPos, node));
++it;
root->appendChildNode(node);
@@ -2443,7 +2537,6 @@ QQuickTextNode *QQuickTextEditPrivate::createTextNode()
Q_Q(QQuickTextEdit);
QQuickTextNode* node = new QQuickTextNode(q);
node->setUseNativeRenderer(renderType == QQuickTextEdit::NativeRendering);
- node->initEngine(color, selectedTextColor, selectionColor);
return node;
}
@@ -2595,6 +2688,15 @@ bool QQuickTextEditPrivate::isLinkHoveredConnected()
*/
/*!
+ \qmlsignal QtQuick::TextEdit::editingFinished()
+ \since 5.6
+
+ This signal is emitted when the text edit loses focus.
+
+ The corresponding handler is \c onEditingFinished.
+*/
+
+/*!
\qmlproperty string QtQuick::TextEdit::hoveredLink
\since 5.2
@@ -2687,7 +2789,132 @@ void QQuickTextEdit::append(const QString &text)
QString QQuickTextEdit::linkAt(qreal x, qreal y) const
{
Q_D(const QQuickTextEdit);
- return d->control->anchorAt(QPointF(x, y));
+ return d->control->anchorAt(QPointF(x + topPadding(), y + leftPadding()));
+}
+
+/*!
+ \since 5.6
+ \qmlproperty real QtQuick::TextEdit::padding
+ \qmlproperty real QtQuick::TextEdit::topPadding
+ \qmlproperty real QtQuick::TextEdit::leftPadding
+ \qmlproperty real QtQuick::TextEdit::bottomPadding
+ \qmlproperty real QtQuick::TextEdit::rightPadding
+
+ These properties hold the padding around the content. This space is reserved
+ in addition to the contentWidth and contentHeight.
+*/
+qreal QQuickTextEdit::padding() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->padding();
+}
+
+void QQuickTextEdit::setPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ updateSize();
+ if (isComponentComplete()) {
+ d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
+ update();
+ }
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickTextEdit::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickTextEdit::topPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setTopPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setTopPadding(padding);
+}
+
+void QQuickTextEdit::resetTopPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickTextEdit::leftPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setLeftPadding(padding);
+}
+
+void QQuickTextEdit::resetLeftPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickTextEdit::rightPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setRightPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setRightPadding(padding);
+}
+
+void QQuickTextEdit::resetRightPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickTextEdit::bottomPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setBottomPadding(padding);
+}
+
+void QQuickTextEdit::resetBottomPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setBottomPadding(0, true);
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index bf6763f772..cfe599c0d3 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -47,12 +47,6 @@ class QTextBlock;
class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(VAlignment)
- Q_ENUMS(HAlignment)
- Q_ENUMS(TextFormat)
- Q_ENUMS(WrapMode)
- Q_ENUMS(SelectionMode)
- Q_ENUMS(RenderType)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
@@ -91,8 +85,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged)
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
- Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument FINAL REVISION 1)
+ Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument CONSTANT FINAL REVISION 1)
Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2)
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ 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)
public:
QQuickTextEdit(QQuickItem *parent=0);
@@ -103,18 +102,21 @@ public:
AlignHCenter = Qt::AlignHCenter,
AlignJustify = Qt::AlignJustify
};
+ Q_ENUM(HAlignment)
enum VAlignment {
AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter
};
+ Q_ENUM(VAlignment)
enum TextFormat {
PlainText = Qt::PlainText,
RichText = Qt::RichText,
AutoText = Qt::AutoText
};
+ Q_ENUM(TextFormat)
enum WrapMode { NoWrap = QTextOption::NoWrap,
WordWrap = QTextOption::WordWrap,
@@ -122,15 +124,18 @@ public:
WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
};
+ Q_ENUM(WrapMode)
enum SelectionMode {
SelectCharacters,
SelectWords
};
+ Q_ENUM(SelectionMode)
enum RenderType { QtRendering,
NativeRendering
};
+ Q_ENUM(RenderType)
QString text() const;
void setText(const QString &);
@@ -247,6 +252,26 @@ public:
Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
Q_SIGNALS:
void textChanged();
void contentSizeChanged();
@@ -283,6 +308,12 @@ Q_SIGNALS:
void baseUrlChanged();
void inputMethodHintsChanged();
void renderTypeChanged();
+ Q_REVISION(6) void editingFinished();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
public Q_SLOTS:
void selectAll();
@@ -321,6 +352,8 @@ private:
void invalidateFontCaches();
protected:
+ QQuickTextEdit(QQuickTextEditPrivate &dd, QQuickItem *parent = 0);
+
void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry) Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index 0cf0f46532..a763f9e56e 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -47,18 +47,19 @@
#include "qquicktextedit_p.h"
#include "qquickimplicitsizeitem_p_p.h"
-#include "qquicktextcontrol_p.h"
#include <QtQml/qqml.h>
#include <QtCore/qlist.h>
+#include <private/qlazilyallocated_p.h>
QT_BEGIN_NAMESPACE
class QTextLayout;
class QQuickTextDocumentWithImageResources;
class QQuickTextControl;
class QQuickTextNode;
+class QQuickTextNodeEngine;
-class QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate
{
public:
Q_DECLARE_PUBLIC(QQuickTextEdit)
@@ -81,10 +82,26 @@ public:
};
typedef QList<Node*>::iterator TextNodeIterator;
+ struct ExtraData {
+ ExtraData();
+
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
QQuickTextEditPrivate()
: color(QRgb(0xFF000000)), selectionColor(QRgb(0xFF000080)), selectedTextColor(QRgb(0xFFFFFFFF))
- , textMargin(0.0), xoff(0), yoff(0), font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0)
+ , textMargin(0.0), xoff(0), yoff(0)
+ , font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0)
, quickDocument(0), lastSelectionStart(0), lastSelectionEnd(0), lineCount(0)
, hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop)
, format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap)
@@ -124,13 +141,19 @@ public:
void setNativeCursorEnabled(bool) {}
void handleFocusEvent(QFocusEvent *event);
- void addCurrentTextNodeToRoot(QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos);
+ void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos);
QQuickTextNode* createTextNode();
#ifndef QT_NO_IM
Qt::InputMethodHints effectiveInputMethodHints() const;
#endif
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
+
QColor color;
QColor selectionColor;
QColor selectedTextColor;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index a4c61209f2..b458f80ce7 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -90,6 +90,13 @@ QQuickTextInput::QQuickTextInput(QQuickItem* parent)
d->init();
}
+QQuickTextInput::QQuickTextInput(QQuickTextInputPrivate &dd, QQuickItem *parent)
+: QQuickImplicitSizeItem(dd, parent)
+{
+ Q_D(QQuickTextInput);
+ d->init();
+}
+
QQuickTextInput::~QQuickTextInput()
{
}
@@ -786,8 +793,8 @@ QRectF QQuickTextInput::cursorRectangle() const
QTextLine l = d->m_textLayout.lineForTextPosition(c);
if (!l.isValid())
return QRectF();
- qreal x = l.cursorToX(c) - d->hscroll;
- qreal y = l.y() - d->vscroll;
+ qreal x = l.cursorToX(c) - d->hscroll + leftPadding();
+ qreal y = l.y() - d->vscroll + topPadding();
return QRectF(x, y, 1, l.height());
}
@@ -910,189 +917,6 @@ void QQuickTextInput::setAutoScroll(bool b)
emit autoScrollChanged(d->autoScroll);
}
-#ifndef QT_NO_VALIDATOR
-
-/*!
- \qmltype IntValidator
- \instantiates QIntValidator
- \inqmlmodule QtQuick
- \ingroup qtquick-text-utility
- \brief Defines a validator for integer values
-
- The IntValidator type provides a validator for integer values.
-
- If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to
- interpret the number and will accept locale specific digits, group separators, and positive
- and negative signs. In addition, IntValidator is always guaranteed to accept a number
- formatted according to the "C" locale.
-*/
-
-
-QQuickIntValidator::QQuickIntValidator(QObject *parent)
- : QIntValidator(parent)
-{
-}
-
-/*!
- \qmlproperty string QtQuick::IntValidator::locale
-
- This property holds the name of the locale used to interpret the number.
-
- \sa {QtQml::Qt::locale()}{Qt.locale()}
-*/
-
-QString QQuickIntValidator::localeName() const
-{
- return locale().name();
-}
-
-void QQuickIntValidator::setLocaleName(const QString &name)
-{
- if (locale().name() != name) {
- setLocale(QLocale(name));
- emit localeNameChanged();
- }
-}
-
-void QQuickIntValidator::resetLocaleName()
-{
- QLocale defaultLocale;
- if (locale() != defaultLocale) {
- setLocale(defaultLocale);
- emit localeNameChanged();
- }
-}
-
-/*!
- \qmlproperty int QtQuick::IntValidator::top
-
- This property holds the validator's highest acceptable value.
- By default, this property's value is derived from the highest signed integer available (typically 2147483647).
-*/
-/*!
- \qmlproperty int QtQuick::IntValidator::bottom
-
- This property holds the validator's lowest acceptable value.
- By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
-*/
-
-/*!
- \qmltype DoubleValidator
- \instantiates QDoubleValidator
- \inqmlmodule QtQuick
- \ingroup qtquick-text-utility
- \brief Defines a validator for non-integer numbers
-
- The DoubleValidator type provides a validator for non-integer numbers.
-
- Input is accepted if it contains a double that is within the valid range
- and is in the correct format.
-
- Input is accepected but invalid if it contains a double that is outside
- the range or is in the wrong format; e.g. with too many digits after the
- decimal point or is empty.
-
- Input is rejected if it is not a double.
-
- Note: If the valid range consists of just positive doubles (e.g. 0.0 to
- 100.0) and input is a negative double then it is rejected. If \l notation
- is set to DoubleValidator.StandardNotation, and the input contains more
- digits before the decimal point than a double in the valid range may have,
- it is also rejected. If \l notation is DoubleValidator.ScientificNotation,
- and the input is not in the valid range, it is accecpted but invalid. The
- value may yet become valid by changing the exponent.
-*/
-
-QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent)
- : QDoubleValidator(parent)
-{
-}
-
-/*!
- \qmlproperty string QtQuick::DoubleValidator::locale
-
- This property holds the name of the locale used to interpret the number.
-
- \sa {QtQml::Qt::locale()}{Qt.locale()}
-*/
-
-QString QQuickDoubleValidator::localeName() const
-{
- return locale().name();
-}
-
-void QQuickDoubleValidator::setLocaleName(const QString &name)
-{
- if (locale().name() != name) {
- setLocale(QLocale(name));
- emit localeNameChanged();
- }
-}
-
-void QQuickDoubleValidator::resetLocaleName()
-{
- QLocale defaultLocale;
- if (locale() != defaultLocale) {
- setLocale(defaultLocale);
- emit localeNameChanged();
- }
-}
-
-#endif // QT_NO_VALIDATOR
-
-/*!
- \qmlproperty real QtQuick::DoubleValidator::top
-
- This property holds the validator's maximum acceptable value.
- By default, this property contains a value of infinity.
-*/
-/*!
- \qmlproperty real QtQuick::DoubleValidator::bottom
-
- This property holds the validator's minimum acceptable value.
- By default, this property contains a value of -infinity.
-*/
-/*!
- \qmlproperty int QtQuick::DoubleValidator::decimals
-
- This property holds the validator's maximum number of digits after the decimal point.
- By default, this property contains a value of 1000.
-*/
-/*!
- \qmlproperty enumeration QtQuick::DoubleValidator::notation
- This property holds the notation of how a string can describe a number.
-
- The possible values for this property are:
-
- \list
- \li DoubleValidator.StandardNotation
- \li DoubleValidator.ScientificNotation (default)
- \endlist
-
- If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
-*/
-
-/*!
- \qmltype RegExpValidator
- \instantiates QRegExpValidator
- \inqmlmodule QtQuick
- \ingroup qtquick-text-utility
- \brief Provides a string validator
-
- The RegExpValidator type provides a validator, which counts as valid any string which
- matches a specified regular expression.
-*/
-/*!
- \qmlproperty regExp QtQuick::RegExpValidator::regExp
-
- This property holds the regular expression used for validation.
-
- Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
- matching "a".
-
- By default, this property contains a regular expression with the pattern .* that matches any string.
-*/
-
/*!
\qmlproperty Validator QtQuick::TextInput::validator
@@ -1489,8 +1313,9 @@ void QQuickTextInput::positionAt(QQmlV4Function *args) const
int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPosition position) const
{
- x += hscroll;
- y += vscroll;
+ Q_Q(const QQuickTextInput);
+ x += hscroll - q->leftPadding();
+ y += vscroll - q->topPadding();
QTextLine line = m_textLayout.lineAt(0);
for (int i = 1; i < m_textLayout.lineCount(); ++i) {
QTextLine nextLine = m_textLayout.lineAt(i);
@@ -1748,7 +1573,7 @@ void QQuickTextInputPrivate::ensureVisible(int position, int preeditCursor, int
{
Q_Q(QQuickTextInput);
QTextLine textLine = m_textLayout.lineForTextPosition(position + preeditCursor);
- const qreal width = qMax<qreal>(0, q->width());
+ const qreal width = qMax<qreal>(0, q->width() - q->leftPadding() - q->rightPadding());
qreal cix = 0;
qreal widthUsed = 0;
if (textLine.isValid()) {
@@ -1811,7 +1636,7 @@ void QQuickTextInputPrivate::updateVerticalScroll()
#ifndef QT_NO_IM
const int preeditLength = m_textLayout.preeditAreaText().length();
#endif
- const qreal height = qMax<qreal>(0, q->height());
+ const qreal height = qMax<qreal>(0, q->height() - q->topPadding() - q->bottomPadding());
qreal heightUsed = contentSize.height();
qreal previousScroll = vscroll;
@@ -1879,14 +1704,15 @@ void QQuickTextInput::invalidateFontCaches()
void QQuickTextInput::ensureActiveFocus()
{
- Q_D(QQuickTextInput);
-
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
#ifndef QT_NO_IM
+ Q_D(QQuickTextInput);
// re-open input panel on press if already focused
if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly)
qGuiApp->inputMethod()->show();
+#else
+ Q_UNUSED(hadActiveFocus);
#endif
}
@@ -1920,13 +1746,13 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
node->deleteContent();
node->setMatrix(QMatrix4x4());
- QPointF offset(0, 0);
+ QPointF offset(leftPadding(), topPadding());
if (d->autoScroll && d->m_textLayout.lineCount() > 0) {
QFontMetricsF fm(d->font);
// the y offset is there to keep the baseline constant in case we have script changes in the text.
- offset = -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent());
+ offset += -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent());
} else {
- offset = -QPointF(d->hscroll, d->vscroll);
+ offset += -QPointF(d->hscroll, d->vscroll);
}
if (!d->m_textLayout.text().isEmpty()
@@ -2672,6 +2498,19 @@ bool QQuickTextInput::isInputMethodComposing() const
#endif
}
+QQuickTextInputPrivate::ExtraData::ExtraData()
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+{
+}
+
void QQuickTextInputPrivate::init()
{
Q_Q(QQuickTextInput);
@@ -2882,7 +2721,7 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const
QTextLine line = layout.createLine();
line.setLineWidth(INT_MAX);
- d->implicitWidth = qCeil(line.naturalTextWidth());
+ d->implicitWidth = qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding();
layout.endLayout();
}
@@ -2890,6 +2729,62 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const
return implicitWidth;
}
+void QQuickTextInputPrivate::setTopPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->topPaddingChanged();
+ }
+}
+
+void QQuickTextInputPrivate::setLeftPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->leftPaddingChanged();
+ }
+}
+
+void QQuickTextInputPrivate::setRightPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->rightPaddingChanged();
+ }
+}
+
+void QQuickTextInputPrivate::setBottomPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->bottomPaddingChanged();
+ }
+}
+
void QQuickTextInputPrivate::updateLayout()
{
Q_Q(QQuickTextInput);
@@ -2915,12 +2810,12 @@ void QQuickTextInputPrivate::updateLayout()
line.setLineWidth(INT_MAX);
const bool wasInLayout = inLayout;
inLayout = true;
- q->setImplicitWidth(qCeil(line.naturalTextWidth()));
+ q->setImplicitWidth(qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding());
inLayout = wasInLayout;
if (inLayout) // probably the result of a binding loop, but by letting it
return; // get this far we'll get a warning to that effect.
}
- qreal lineWidth = q->widthValid() ? q->width() : INT_MAX;
+ qreal lineWidth = q->widthValid() ? q->width() - q->leftPadding() - q->rightPadding() : INT_MAX;
qreal height = 0;
qreal width = 0;
do {
@@ -2947,9 +2842,9 @@ void QQuickTextInputPrivate::updateLayout()
q->update();
if (!requireImplicitWidth && !q->widthValid())
- q->setImplicitSize(width, height);
+ q->setImplicitSize(width + q->leftPadding() + q->rightPadding(), height + q->topPadding() + q->bottomPadding());
else
- q->setImplicitHeight(height);
+ q->setImplicitHeight(height + q->topPadding() + q->bottomPadding());
updateBaselineOffset();
@@ -2971,13 +2866,13 @@ void QQuickTextInputPrivate::updateBaselineOffset()
QFontMetricsF fm(font);
qreal yoff = 0;
if (q->heightValid()) {
- const qreal surplusHeight = q->height() - contentSize.height();
+ const qreal surplusHeight = q->height() - contentSize.height() - q->topPadding() - q->bottomPadding();
if (vAlign == QQuickTextInput::AlignBottom)
yoff = surplusHeight;
else if (vAlign == QQuickTextInput::AlignVCenter)
yoff = surplusHeight/2;
}
- q->setBaselineOffset(fm.ascent() + yoff);
+ q->setBaselineOffset(fm.ascent() + yoff + q->topPadding());
}
#ifndef QT_NO_CLIPBOARD
@@ -3345,7 +3240,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
m_preeditCursor = event->preeditString().length();
hasImState = !event->preeditString().isEmpty();
bool cursorVisible = true;
- QList<QTextLayout::FormatRange> formats;
+ QVector<QTextLayout::FormatRange> formats;
for (int i = 0; i < event->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
if (a.type == QInputMethodEvent::Cursor) {
@@ -3364,7 +3259,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
}
}
}
- m_textLayout.setAdditionalFormats(formats);
+ m_textLayout.setFormats(formats);
updateDisplayText(/*force*/ true);
if ((cursorPositionChanged && !emitCursorPositionChanged())
@@ -4273,6 +4168,21 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
return;
}
+ if (m_blinkPeriod > 0) {
+ if (m_blinkTimer)
+ q->killTimer(m_blinkTimer);
+
+ m_blinkTimer = q->startTimer(m_blinkPeriod / 2);
+
+ if (m_blinkStatus == 0) {
+ m_blinkStatus = 1;
+
+ updateType = UpdatePaintNode;
+ q->polish();
+ q->update();
+ }
+ }
+
if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit
&& !m_passwordEchoEditing
&& !m_readOnly
@@ -4508,5 +4418,126 @@ void QQuickTextInput::ensureVisible(int position)
updateCursorRectangle(false);
}
+/*!
+ \since 5.6
+ \qmlproperty real QtQuick::TextInput::padding
+ \qmlproperty real QtQuick::TextInput::topPadding
+ \qmlproperty real QtQuick::TextInput::leftPadding
+ \qmlproperty real QtQuick::TextInput::bottomPadding
+ \qmlproperty real QtQuick::TextInput::rightPadding
+
+ These properties hold the padding around the content. This space is reserved
+ in addition to the contentWidth and contentHeight.
+*/
+qreal QQuickTextInput::padding() const
+{
+ Q_D(const QQuickTextInput);
+ return d->padding();
+}
+
+void QQuickTextInput::setPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ d->updateLayout();
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickTextInput::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickTextInput::topPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setTopPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setTopPadding(padding);
+}
+
+void QQuickTextInput::resetTopPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickTextInput::leftPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setLeftPadding(padding);
+}
+
+void QQuickTextInput::resetLeftPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickTextInput::rightPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setRightPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setRightPadding(padding);
+}
+
+void QQuickTextInput::resetRightPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickTextInput::bottomPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setBottomPadding(padding);
+}
+
+void QQuickTextInput::resetBottomPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setBottomPadding(0, true);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 3bcbe0fa25..b91149f5f3 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -45,13 +45,6 @@ class QValidator;
class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
- Q_ENUMS(WrapMode)
- Q_ENUMS(EchoMode)
- Q_ENUMS(SelectionMode)
- Q_ENUMS(CursorPosition)
- Q_ENUMS(RenderType)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(int length READ length NOTIFY textChanged)
@@ -96,6 +89,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentSizeChanged)
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ 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)
+
public:
QQuickTextInput(QQuickItem * parent=0);
~QQuickTextInput();
@@ -108,18 +107,21 @@ public:
Password,
PasswordEchoOnEdit
};
+ Q_ENUM(EchoMode)
enum HAlignment {
AlignLeft = Qt::AlignLeft,
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter
};
+ Q_ENUM(HAlignment)
enum VAlignment {
AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter
};
+ Q_ENUM(VAlignment)
enum WrapMode {
NoWrap = QTextOption::NoWrap,
@@ -128,20 +130,24 @@ public:
WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
};
+ Q_ENUM(WrapMode)
enum SelectionMode {
SelectCharacters,
SelectWords
};
+ Q_ENUM(SelectionMode)
enum CursorPosition {
CursorBetweenCharacters,
CursorOnCharacter
};
+ Q_ENUM(CursorPosition)
enum RenderType { QtRendering,
NativeRendering
};
+ Q_ENUM(RenderType)
//Auxilliary functions needed to control the TextInput from QML
Q_INVOKABLE void positionAt(QQmlV4Function *args) const;
@@ -260,6 +266,26 @@ public:
qreal contentWidth() const;
qreal contentHeight() const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
Q_SIGNALS:
void textChanged();
void cursorPositionChanged();
@@ -300,12 +326,19 @@ Q_SIGNALS:
void contentSizeChanged();
void inputMethodHintsChanged();
void renderTypeChanged();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
private:
void invalidateFontCaches();
void ensureActiveFocus();
protected:
+ QQuickTextInput(QQuickTextInputPrivate &dd, QQuickItem *parent = 0);
+
void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry) Q_DECL_OVERRIDE;
@@ -360,46 +393,8 @@ private:
Q_DECLARE_PRIVATE(QQuickTextInput)
};
-#ifndef QT_NO_VALIDATOR
-class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator
-{
- Q_OBJECT
- Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
-public:
- QQuickIntValidator(QObject *parent = 0);
-
- QString localeName() const;
- void setLocaleName(const QString &name);
- void resetLocaleName();
-
-Q_SIGNALS:
- void localeNameChanged();
-};
-
-class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator
-{
- Q_OBJECT
- Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
-public:
- QQuickDoubleValidator(QObject *parent = 0);
-
- QString localeName() const;
- void setLocaleName(const QString &name);
- void resetLocaleName();
-
-Q_SIGNALS:
- void localeNameChanged();
-};
-#endif
-
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickTextInput)
-#ifndef QT_NO_VALIDATOR
-QML_DECLARE_TYPE(QValidator)
-QML_DECLARE_TYPE(QQuickIntValidator)
-QML_DECLARE_TYPE(QQuickDoubleValidator)
-QML_DECLARE_TYPE(QRegExpValidator)
-#endif
#endif // QQUICKTEXTINPUT_P_H
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 3038573bb3..cf0a6f5273 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -47,6 +47,7 @@
#include <QtGui/qpalette.h>
#include <QtGui/qtextlayout.h>
#include <QtGui/qstylehints.h>
+#include <private/qlazilyallocated_p.h>
#include "qplatformdefs.h"
@@ -64,13 +65,28 @@ QT_BEGIN_NAMESPACE
class QQuickTextNode;
-class Q_AUTOTEST_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate
{
public:
Q_DECLARE_PUBLIC(QQuickTextInput)
typedef QQuickTextInput Public;
+ struct ExtraData {
+ ExtraData();
+
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
QQuickTextInputPrivate()
: hscroll(0)
, vscroll(0)
@@ -420,6 +436,12 @@ public:
qreal getImplicitWidth() const Q_DECL_OVERRIDE;
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
+
private:
void removeSelectedText();
void internalSetText(const QString &txt, int pos = -1, bool edited = true);
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 010a443d18..d40dedd798 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -186,17 +186,6 @@ void QQuickTextNode::clearCursor()
m_cursorNode = 0;
}
-void QQuickTextNode::initEngine(const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor, const QColor& anchorColor, const QPointF &position)
-{
- m_engine.reset(new QQuickTextNodeEngine);
- m_engine->m_hasContents = false;
- m_engine->setTextColor(textColor);
- m_engine->setSelectedTextColor(selectedTextColor);
- m_engine->setSelectionColor(selectionColor);
- m_engine->setAnchorColor(anchorColor);
- m_engine->setPosition(position);
-}
-
void QQuickTextNode::addRectangleNode(const QRectF &rect, const QColor &color)
{
QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext();
@@ -224,7 +213,12 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
const QColor &selectionColor, const QColor &selectedTextColor,
int selectionStart, int selectionEnd)
{
- initEngine(textColor, selectedTextColor, selectionColor, anchorColor);
+ QQuickTextNodeEngine engine;
+ engine.setTextColor(textColor);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+ engine.setAnchorColor(anchorColor);
+ engine.setPosition(position);
QList<QTextFrame *> frames;
frames.append(textDocument->rootFrame());
@@ -232,7 +226,7 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
QTextFrame *textFrame = frames.takeFirst();
frames.append(textFrame->childFrames());
- m_engine->addFrameDecorations(textDocument, textFrame);
+ engine.addFrameDecorations(textDocument, textFrame);
if (textFrame->firstPosition() > textFrame->lastPosition()
&& textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
@@ -242,23 +236,23 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
QRectF rect = a->frameBoundingRect(textFrame);
QTextBlock block = textFrame->firstCursorPosition().block();
- m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- m_engine->addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument,
+ engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
+ engine.addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument,
pos, textFrame->frameFormat().position());
} else {
QTextFrame::iterator it = textFrame->begin();
while (!it.atEnd()) {
- Q_ASSERT(!m_engine->currentLine().isValid());
+ Q_ASSERT(!engine.currentLine().isValid());
QTextBlock block = it.currentBlock();
- m_engine->addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd);
+ engine.addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd);
++it;
}
}
}
- m_engine->addToSceneGraph(this, style, styleColor);
+ engine.addToSceneGraph(this, style, styleColor);
}
void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
@@ -268,7 +262,12 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
int selectionStart, int selectionEnd,
int lineStart, int lineCount)
{
- initEngine(color, selectedTextColor, selectionColor, anchorColor, position);
+ QQuickTextNodeEngine engine;
+ engine.setTextColor(color);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+ engine.setAnchorColor(anchorColor);
+ engine.setPosition(position);
#ifndef QT_NO_IM
int preeditLength = textLayout->preeditAreaText().length();
@@ -276,7 +275,7 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
#endif
QVarLengthArray<QTextLayout::FormatRange> colorChanges;
- m_engine->mergeFormats(textLayout, &colorChanges);
+ engine.mergeFormats(textLayout, &colorChanges);
lineCount = lineCount >= 0
? qMin(lineStart + lineCount, textLayout->lineCount())
@@ -297,11 +296,11 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
}
#endif
- m_engine->setCurrentLine(line);
- m_engine->addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
+ engine.setCurrentLine(line);
+ engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
}
- m_engine->addToSceneGraph(this, style, styleColor);
+ engine.addToSceneGraph(this, style, styleColor);
}
void QQuickTextNode::deleteContent()
diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h
index c7b9804ea6..31cc23bf2a 100644
--- a/src/quick/items/qquicktextnode_p.h
+++ b/src/quick/items/qquicktextnode_p.h
@@ -101,14 +101,10 @@ public:
void setUseNativeRenderer(bool on) { m_useNativeRenderer = on; }
private:
- void initEngine(const QColor &textColor, const QColor &selectedTextColor, const QColor &selectionColor, const QColor& anchorColor = QColor()
- , const QPointF &position = QPointF());
-
QSGRectangleNode *m_cursorNode;
QList<QSGTexture *> m_textures;
QQuickItem *m_ownerElement;
bool m_useNativeRenderer;
- QScopedPointer<QQuickTextNodeEngine> m_engine;
friend class QQuickTextEdit;
friend class QQuickTextEditPrivate;
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 7903f79e89..204b135b8c 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -884,7 +884,7 @@ void QQuickTextNodeEngine::mergeFormats(QTextLayout *textLayout, QVarLengthArray
if (textLayout == 0)
return;
- QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
+ QVector<QTextLayout::FormatRange> additionalFormats = textLayout->formats();
for (int i=0; i<additionalFormats.size(); ++i) {
QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h
index 2f6cacf601..f9ebe43183 100644
--- a/src/quick/items/qquicktextnodeengine_p.h
+++ b/src/quick/items/qquicktextnodeengine_p.h
@@ -231,8 +231,6 @@ private:
QList<TextDecoration> m_lines;
QVector<BinaryTreeNode> m_processedNodes;
- QList<QPair<QRectF, QImage> > m_images;
-
bool m_hasSelection : 1;
bool m_hasContents : 1;
friend class QQuickTextNode;
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 5b5413a4ba..6582e3ad40 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -345,6 +345,9 @@ QQuickView::Status QQuickView::status() const
if (!d->component)
return QQuickView::Null;
+ if (d->component->status() == QQmlComponent::Ready && !d->root)
+ return QQuickView::Error;
+
return QQuickView::Status(d->component->status());
}
@@ -364,6 +367,10 @@ QList<QQmlError> QQuickView::errors() const
QQmlError error;
error.setDescription(QLatin1String("QQuickView: invalid qml engine."));
errs << error;
+ } else if (d->component->status() == QQmlComponent::Ready && !d->root) {
+ QQmlError error;
+ error.setDescription(QLatin1String("QQuickView: invalid root object."));
+ errs << error;
}
return errs;
@@ -501,14 +508,15 @@ void QQuickViewPrivate::setRootObject(QObject *obj)
if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
root = sgItem;
sgItem->setParentItem(q->QQuickWindow::contentItem());
+ } else if (qobject_cast<QWindow *>(obj)) {
+ qWarning() << "QQuickView does not support using windows as a root item." << endl
+ << endl
+ << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl;
} else {
qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl
<< endl
- << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
- << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
- << endl
- << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
- << "QDeclarativeView class in the Qt Quick 1 module." << endl;
+ << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl
+ << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl;
delete obj;
root = 0;
}
diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h
index f094c5a216..80da0ba4f1 100644
--- a/src/quick/items/qquickview.h
+++ b/src/quick/items/qquickview.h
@@ -53,7 +53,6 @@ class Q_QUICK_EXPORT QQuickView : public QQuickWindow
Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
- Q_ENUMS(ResizeMode Status)
public:
explicit QQuickView(QWindow *parent = 0);
QQuickView(QQmlEngine* engine, QWindow *parent);
@@ -68,10 +67,12 @@ public:
QQuickItem *rootObject() const;
enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ Q_ENUM(ResizeMode)
ResizeMode resizeMode() const;
void setResizeMode(ResizeMode);
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
QList<QQmlError> errors() const;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 84b585e3b5..6b6b86c1e2 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -83,8 +83,8 @@ bool QQuickWindowPrivate::defaultAlphaBuffer = false;
void QQuickWindowPrivate::updateFocusItemTransform()
{
- Q_Q(QQuickWindow);
#ifndef QT_NO_IM
+ Q_Q(QQuickWindow);
QQuickItem *focus = q->activeFocusItem();
if (focus && QGuiApplication::focusObject() == focus) {
QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus);
@@ -259,8 +259,7 @@ void QQuickWindowPrivate::polishItems()
// the user.
int recursionSafeguard = INT_MAX;
while (!itemsToPolish.isEmpty() && --recursionSafeguard > 0) {
- QQuickItem *item = *itemsToPolish.begin();
- itemsToPolish.remove(item);
+ QQuickItem *item = itemsToPolish.takeLast();
QQuickItemPrivate::get(item)->polishScheduled = false;
item->updatePolish();
}
@@ -2386,7 +2385,9 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
if (target->childMouseEventFilter(item, targetEvent.data())) {
qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target;
QVector<int> touchIds;
- for (int i = 0; i < targetEvent->touchPoints().size(); ++i)
+ const int touchPointCount = targetEvent->touchPoints().size();
+ touchIds.reserve(touchPointCount);
+ for (int i = 0; i < touchPointCount; ++i)
touchIds.append(targetEvent->touchPoints().at(i).id());
target->grabTouchPoints(touchIds);
if (mouseGrabberItem) {
@@ -2730,7 +2731,7 @@ static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
QQuickItem *before = 0;
for (int i=0; i<childItems.size(); ++i) {
QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i));
- // Perform the same check as the in buildOrderNodeList below.
+ // Perform the same check as the in fetchNextNode below.
if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
before = childItems.at(i);
else
@@ -2739,13 +2740,9 @@ static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : 0;
}
-static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv)
+static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
{
QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
- QVector<QSGNode *> desiredNodes;
- desiredNodes.reserve(orderedChildren.size() + 1); // + 1 for the paintNode
-
- int ii = 0;
for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
@@ -2753,11 +2750,14 @@ static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv)
(!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
continue;
- desiredNodes.append(childPrivate->itemNode());
+ ii++;
+ return childPrivate->itemNode();
}
- if (itemPriv->paintNode)
- desiredNodes.append(itemPriv->paintNode);
+ if (itemPriv->paintNode && !returnedPaintNode) {
+ returnedPaintNode = true;
+ return itemPriv->paintNode;
+ }
for (; ii < orderedChildren.count(); ++ii) {
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
@@ -2765,10 +2765,11 @@ static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv)
(!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
continue;
- desiredNodes.append(childPrivate->itemNode());
+ ii++;
+ return childPrivate->itemNode();
}
- return desiredNodes;
+ return 0;
}
void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
@@ -2871,7 +2872,10 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
}
if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
- QVector<QSGNode *> desiredNodes = buildOrderedNodeList(itemPriv);
+ int ii = 0;
+ bool fetchedPaintNode = false;
+ QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
+ int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0);
// now start making current state match the promised land of
// desiredNodes. in the case of our current state matching desiredNodes
@@ -2889,14 +2893,9 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
int added = 0;
int removed = 0;
int replaced = 0;
-#if defined(CHILDRENUPDATE_DEBUG)
- // This is slow! Do not do this in a normal/profiling build!
- int initialCount = groupNode->childCount();
-#endif
-
- while (currentNode && desiredNodesProcessed < desiredNodes.size()) {
- QSGNode *desiredNode = desiredNodes.at(desiredNodesProcessed);
+ QSGNode *desiredNode = 0;
+ while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
// uh oh... reality and our utopic paradise are diverging!
// we need to reconcile this...
if (currentNode != desiredNode) {
@@ -2920,9 +2919,8 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
// if we didn't process as many nodes as in the new list, then we have
// more nodes at the end of desiredNodes to append to our list.
// this will be the case when adding new nodes, for instance.
- if (desiredNodesProcessed < desiredNodes.size()) {
- for (int i = desiredNodesProcessed; i < desiredNodes.size(); ++i) {
- QSGNode *desiredNode = desiredNodes.at(i);
+ if (desiredNodesProcessed < desiredNodesSize) {
+ while ((desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
if (desiredNode->parent())
desiredNode->parent()->removeChildNode(desiredNode);
groupNode->appendChildNode(desiredNode);
@@ -2939,10 +2937,6 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
removed++;
}
}
-
-#if defined(CHILDRENUPDATE_DEBUG)
- qDebug() << "Done children update for " << itemPriv << "- before:" << initialCount << "after:" << groupNode->childCount() << "added:" << added << "removed:" << removed << "replaced:" << replaced;
-#endif
}
if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
@@ -3308,12 +3302,7 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
QImage QQuickWindow::grabWindow()
{
Q_D(QQuickWindow);
- if (!isVisible()) {
-
- if (d->context->openglContext()) {
- qWarning("QQuickWindow::grabWindow: scene graph already in use");
- return QImage();
- }
+ if (!isVisible() && !d->context->openglContext()) {
if (!handle() || !size().isValid()) {
qWarning("QQuickWindow::grabWindow: window must be created and have a valid size");
@@ -3383,6 +3372,11 @@ QQmlIncubationController *QQuickWindow::incubationController() const
will delete the GL texture when the texture object is deleted.
\value TextureCanUseAtlas The image can be uploaded into a texture atlas.
+
+ \value TextureIsOpaque The texture will return false for
+ QSGTexture::hasAlphaChannel() and will not be blended. This flag was added
+ in Qt 5.6.
+
*/
/*!
@@ -3587,12 +3581,21 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
The caller of the function is responsible for deleting the returned texture.
The actual GL texture will be deleted when the texture object is deleted.
- When \a options contains TextureCanUseAtlas the engine may put the image
+ When \a options contains TextureCanUseAtlas, the engine may put the image
into a texture atlas. Textures in an atlas need to rely on
QSGTexture::normalizedTextureSubRect() for their geometry and will not
support QSGTexture::Repeat. Other values from CreateTextureOption are
ignored.
+ When \a options contains TextureIsOpaque, the engine will create an RGB
+ texture which returns false for QSGTexture::hasAlphaChannel(). Opaque
+ textures will in most cases be faster to render. When this flag is not set,
+ the texture will have an alpha channel based on the image's format.
+
+ When \a options contains TextureHasMipmaps, the engine will create a
+ texture which can use mipmap filtering. Mipmapped textures can not be in
+ an atlas.
+
The returned texture will be using \c GL_TEXTURE_2D as texture target and
\c GL_RGBA as internal format. Reimplement QSGTexture to create textures
with different parameters.
@@ -3614,14 +3617,13 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
{
Q_D(const QQuickWindow);
- if (d->context) {
- if (options & TextureCanUseAtlas)
- return d->context->createTexture(image);
- else
- return d->context->createTextureNoAtlas(image);
- }
- else
- return 0;
+ if (!d->context)
+ return 0;
+ uint flags = 0;
+ if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
+ if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap;
+ if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
+ return d->context->createTexture(image, flags);
}
@@ -4116,6 +4118,7 @@ void QQuickWindow::resetOpenGLState()
\value BeforeRenderingStage Before rendering.
\value AfterRenderingStage After rendering.
\value AfterSwapStage After the frame is swapped.
+ \value NoStage As soon as possible. This value was added in Qt 5.6.
\sa {Scene Graph and Rendering}
*/
@@ -4141,8 +4144,17 @@ void QQuickWindow::resetOpenGLState()
If the rendering is happening on a different thread, then the job
will happen on the rendering thread.
- \note This function does not trigger rendering; the job
- will be stored run until rendering is triggered elsewhere.
+ If \a stage is \l NoStage, \a job will be run at the earliest opportunity
+ whenever the render thread is not busy rendering a frame. If there is no
+ OpenGL context available or the window is not exposed at the time the job is
+ either posted or handled, it is deleted without executing the run() method.
+ If a non-threaded renderer is in use, the run() method of the job is executed
+ synchronously.
+ The OpenGL context is changed to the renderer context before executing a
+ \l NoStage job.
+
+ \note This function does not trigger rendering; the jobs targeting any other
+ stage than NoStage will be stored run until rendering is triggered elsewhere.
To force the job to run earlier, call QQuickWindow::update();
\sa beforeRendering(), afterRendering(), beforeSynchronizing(),
@@ -4154,16 +4166,22 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
Q_D(QQuickWindow);
d->renderJobMutex.lock();
- if (stage == BeforeSynchronizingStage)
+ if (stage == BeforeSynchronizingStage) {
d->beforeSynchronizingJobs << job;
- else if (stage == AfterSynchronizingStage)
+ } else if (stage == AfterSynchronizingStage) {
d->afterSynchronizingJobs << job;
- else if (stage == BeforeRenderingStage)
+ } else if (stage == BeforeRenderingStage) {
d->beforeRenderingJobs << job;
- else if (stage == AfterRenderingStage)
+ } else if (stage == AfterRenderingStage) {
d->afterRenderingJobs << job;
- else if (stage == AfterSwapStage)
+ } else if (stage == AfterSwapStage) {
d->afterSwapJobs << job;
+ } else if (stage == NoStage) {
+ if (isExposed())
+ d->windowManager->postJob(this, job);
+ else
+ delete job;
+ }
d->renderJobMutex.unlock();
}
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index f7a1956120..eb894d2271 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -69,7 +69,8 @@ public:
TextureHasAlphaChannel = 0x0001,
TextureHasMipmaps = 0x0002,
TextureOwnsGLTexture = 0x0004,
- TextureCanUseAtlas = 0x0008
+ TextureCanUseAtlas = 0x0008,
+ TextureIsOpaque = 0x0010,
};
enum RenderStage {
@@ -77,7 +78,8 @@ public:
AfterSynchronizingStage,
BeforeRenderingStage,
AfterRenderingStage,
- AfterSwapStage
+ AfterSwapStage,
+ NoStage
};
Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
@@ -85,7 +87,7 @@ public:
enum SceneGraphError {
ContextNotAvailable = 1
};
- Q_ENUMS(SceneGraphError)
+ Q_ENUM(SceneGraphError)
QQuickWindow(QWindow *parent = 0);
explicit QQuickWindow(QQuickRenderControl *renderControl);
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 605a36fb1d..0d33d2398a 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -200,7 +200,7 @@ public:
QQuickItem *dirtyItemList;
QList<QSGNode *> cleanupNodeList;
- QSet<QQuickItem *> itemsToPolish;
+ QVector<QQuickItem *> itemsToPolish;
void updateDirtyNodes();
void cleanupNodes();
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 524ee02952..6027a6ddc1 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -133,7 +133,6 @@ void QQmlQtQuick2DebugStatesDelegate::updateBinding(QQmlContext *context,
QQmlContextData::get(context), fileName,
line, column);
newBinding->setTarget(property);
- newBinding->setNotifyOnValueChanged(true);
}
state->changeBindingInRevertList(object, propertyName, newBinding);
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 63938d50a9..f49fedbbf6 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -198,9 +198,9 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
void ShaderManager::invalidated()
{
- qDeleteAll(stockShaders.values());
+ qDeleteAll(stockShaders);
stockShaders.clear();
- qDeleteAll(rewrittenShaders.values());
+ qDeleteAll(rewrittenShaders);
rewrittenShaders.clear();
delete blitProgram;
blitProgram = 0;
@@ -1081,6 +1081,9 @@ void Renderer::nodeWasRemoved(Node *node)
if (e) {
e->removed = true;
m_elementsToDelete.add(e);
+
+ if (m_renderNodeElements.isEmpty())
+ m_useDepthBuffer = context()->openglContext()->format().depthBufferSize() > 0;
}
}
@@ -2547,8 +2550,15 @@ void Renderer::render()
QSGNodeDumper::dump(rootNode());
}
- if (Q_UNLIKELY(debug_render() || debug_build())) {
+ QElapsedTimer timer;
+ quint64 timeRenderLists = 0;
+ quint64 timePrepareOpaque = 0;
+ quint64 timePrepareAlpha = 0;
+ quint64 timeSorting = 0;
+ quint64 timeUploadOpaque = 0;
+ quint64 timeUploadAlpha = 0;
+ if (Q_UNLIKELY(debug_render() || debug_build())) {
QByteArray type("rebuild:");
if (m_rebuild == 0)
type += " none";
@@ -2564,6 +2574,7 @@ void Renderer::render()
}
qDebug() << "Renderer::render()" << this << type;
+ timer.start();
}
if (m_vao)
@@ -2590,6 +2601,7 @@ void Renderer::render()
}
}
}
+ if (Q_UNLIKELY(debug_render())) timeRenderLists = timer.restart();
for (int i=0; i<m_opaqueBatches.size(); ++i)
m_opaqueBatches.at(i)->cleanupRemovedElements();
@@ -2602,7 +2614,9 @@ void Renderer::render()
if (m_rebuild & BuildBatches) {
prepareOpaqueBatches();
+ if (Q_UNLIKELY(debug_render())) timePrepareOpaque = timer.restart();
prepareAlphaBatches();
+ if (Q_UNLIKELY(debug_render())) timePrepareAlpha = timer.restart();
if (Q_UNLIKELY(debug_build())) {
qDebug() << "Opaque Batches:";
@@ -2622,8 +2636,11 @@ void Renderer::render()
}
}
}
+ } else {
+ if (Q_UNLIKELY(debug_render())) timePrepareOpaque = timePrepareAlpha = timer.restart();
}
+
deleteRemovedElements();
if (m_rebuild != 0) {
@@ -2639,6 +2656,8 @@ void Renderer::render()
m_zRange = 1.0 / (m_nextRenderOrder);
}
+ if (Q_UNLIKELY(debug_render())) timeSorting = timer.restart();
+
int largestVBO = 0;
#ifdef QSG_SEPARATE_INDEX_BUFFER
int largestIBO = 0;
@@ -2653,6 +2672,8 @@ void Renderer::render()
#endif
uploadBatch(b);
}
+ if (Q_UNLIKELY(debug_render())) timeUploadOpaque = timer.restart();
+
if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Alpha Batches:";
for (int i=0; i<m_alphaBatches.size(); ++i) {
@@ -2663,6 +2684,7 @@ void Renderer::render()
largestIBO = qMax(b->ibo.size, largestIBO);
#endif
}
+ if (Q_UNLIKELY(debug_render())) timeUploadAlpha = timer.restart();
if (largestVBO * 2 < m_vertexUploadPool.size())
m_vertexUploadPool.resize(largestVBO * 2);
@@ -2673,6 +2695,15 @@ void Renderer::render()
renderBatches();
+ if (Q_UNLIKELY(debug_render())) {
+ qDebug(" -> times: build: %d, prepare(opaque/alpha): %d/%d, sorting: %d, upload(opaque/alpha): %d/%d, render: %d",
+ (int) timeRenderLists,
+ (int) timePrepareOpaque, (int) timePrepareAlpha,
+ (int) timeSorting,
+ (int) timeUploadOpaque, (int) timeUploadAlpha,
+ (int) timer.elapsed());
+ }
+
m_rebuild = 0;
m_renderOrderRebuildLower = -1;
m_renderOrderRebuildUpper = -1;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index f87dd75c8c..c7b5f73688 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -100,6 +100,7 @@ template <typename Type, int PageSize> class Allocator
{
public:
Allocator()
+ : m_freePage(0)
{
pages.push_back(new AllocatorPage<Type, PageSize>());
}
@@ -112,14 +113,21 @@ public:
Type *allocate()
{
AllocatorPage<Type, PageSize> *p = 0;
- for (int i=0; i<pages.size(); ++i) {
+ for (int i = m_freePage; i < pages.size(); i++) {
if (pages.at(i)->available > 0) {
p = pages.at(i);
+ m_freePage = i;
break;
}
}
+
+ // we couldn't find a free page from m_freePage to the last page.
+ // either there is no free pages, or there weren't any in the area we
+ // scanned: rescanning is expensive, so let's just assume there isn't
+ // one. when an item is released, we'll reset m_freePage anyway.
if (!p) {
p = new AllocatorPage<Type, PageSize>();
+ m_freePage = pages.count();
pages.push_back(p);
}
uint pos = p->blocks[PageSize - p->available];
@@ -151,6 +159,9 @@ public:
delete page;
page = pages.back();
}
+
+ // Reset the free page to force a scan for a new free point.
+ m_freePage = 0;
}
void release(Type *t)
@@ -172,6 +183,7 @@ public:
}
QVector<AllocatorPage<Type, PageSize> *> pages;
+ int m_freePage;
};
@@ -500,8 +512,8 @@ public:
ShaderManager(QSGRenderContext *ctx) : blitProgram(0), visualizeProgram(0), context(ctx) { }
~ShaderManager() {
- qDeleteAll(rewrittenShaders.values());
- qDeleteAll(stockShaders.values());
+ qDeleteAll(rewrittenShaders);
+ qDeleteAll(stockShaders);
}
public Q_SLOTS:
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 4f5c4efe14..bf97133e97 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -165,7 +165,9 @@ void QSGDistanceFieldGlyphCache::update()
Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphAdaptationLayerFrame);
QList<QDistanceField> distanceFields;
- for (int i = 0; i < m_pendingGlyphs.size(); ++i) {
+ const int pendingGlyphsSize = m_pendingGlyphs.size();
+ distanceFields.reserve(pendingGlyphsSize);
+ for (int i = 0; i < pendingGlyphsSize; ++i) {
GlyphData &gd = glyphData(m_pendingGlyphs.at(i));
distanceFields.append(QDistanceField(gd.path,
m_pendingGlyphs.at(i),
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 418d571ae6..d3879d2958 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -41,7 +41,6 @@
#include <QtQuick/private/qsgdefaultglyphnode_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p_p.h>
-#include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h>
#include <QtQuick/private/qsgatlastexture_p.h>
#include <QtQuick/private/qsgrenderloop_p.h>
#include <QtQuick/private/qsgdefaultlayer_p.h>
@@ -60,9 +59,6 @@
#include <QtQuick/private/qsgtexture_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/private/qabstractanimation_p.h>
-#include <qpa/qplatformintegration.h>
-
-#include <qpa/qplatformsharedgraphicscache.h>
#include <private/qobject_p.h>
#include <qmutex.h>
@@ -572,35 +568,7 @@ QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRaw
QSGDistanceFieldGlyphCache *cache = m_distanceFieldCacheManager->cache(font);
if (!cache) {
- QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
- if (platformIntegration != 0
- && platformIntegration->hasCapability(QPlatformIntegration::SharedGraphicsCache)) {
- QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
- if (!fe->faceId().filename.isEmpty()) {
- QByteArray keyName = fe->faceId().filename;
- if (font.style() != QFont::StyleNormal)
- keyName += QByteArray(" I");
- if (font.weight() != QFont::Normal)
- keyName += ' ' + QByteArray::number(font.weight());
- keyName += QByteArray(" DF");
- QPlatformSharedGraphicsCache *sharedGraphicsCache =
- platformIntegration->createPlatformSharedGraphicsCache(keyName);
-
- if (sharedGraphicsCache != 0) {
- sharedGraphicsCache->ensureCacheInitialized(keyName,
- QPlatformSharedGraphicsCache::OpenGLTexture,
- QPlatformSharedGraphicsCache::Alpha8);
-
- cache = new QSGSharedDistanceFieldGlyphCache(keyName,
- sharedGraphicsCache,
- m_distanceFieldCacheManager,
- openglContext(),
- font);
- }
- }
- }
- if (!cache)
- cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
+ cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
m_distanceFieldCacheManager->insertCache(font, cache);
}
@@ -676,7 +644,7 @@ void QSGRenderContext::invalidate()
qDeleteAll(m_texturesToDelete);
m_texturesToDelete.clear();
- qDeleteAll(m_textures.values());
+ qDeleteAll(m_textures);
m_textures.clear();
/* The cleanup of the atlas textures is a bit intriguing.
@@ -767,22 +735,26 @@ QSGDepthStencilBufferManager *QSGRenderContext::depthStencilBufferManager()
will be called with \a image as argument.
*/
-QSGTexture *QSGRenderContext::createTexture(const QImage &image) const
+QSGTexture *QSGRenderContext::createTexture(const QImage &image, uint flags) const
{
- if (!openglContext())
- return 0;
- QSGTexture *t = m_atlasManager->create(image);
- if (t)
- return t;
- return createTextureNoAtlas(image);
-}
+ bool atlas = flags & CreateTexture_Atlas;
+ bool mipmap = flags & CreateTexture_Mipmap;
+ bool alpha = flags & CreateTexture_Alpha;
-QSGTexture *QSGRenderContext::createTextureNoAtlas(const QImage &image) const
-{
- QSGPlainTexture *t = new QSGPlainTexture();
- if (!image.isNull())
- t->setImage(image);
- return t;
+ // The atlas implementation is only supported from the render thread and
+ // does not support mipmaps.
+ if (!mipmap && atlas && openglContext() && QThread::currentThread() == openglContext()->thread()) {
+ QSGTexture *t = m_atlasManager->create(image, alpha);
+ if (t)
+ return t;
+ }
+
+ QSGPlainTexture *texture = new QSGPlainTexture();
+ texture->setImage(image);
+ if (texture->hasAlphaChannel() && !alpha)
+ texture->setHasAlphaChannel(false);
+
+ return texture;
}
/*!
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index d1897f20f9..49b6f6e2a0 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -88,6 +88,12 @@ class Q_QUICK_PRIVATE_EXPORT QSGRenderContext : public QObject
{
Q_OBJECT
public:
+ enum CreateTextureFlags {
+ CreateTexture_Alpha = 0x1,
+ CreateTexture_Atlas = 0x2,
+ CreateTexture_Mipmap = 0x4
+ };
+
QSGRenderContext(QSGContext *context);
~QSGRenderContext();
@@ -107,8 +113,8 @@ public:
virtual QSGDistanceFieldGlyphCache *distanceFieldGlyphCache(const QRawFont &font);
QSGTexture *textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window);
- virtual QSGTexture *createTexture(const QImage &image) const;
- virtual QSGTexture *createTextureNoAtlas(const QImage &image) const;
+ virtual QSGTexture *createTexture(const QImage &image, uint flags = CreateTexture_Alpha) const;
+
virtual QSGRenderer *createRenderer();
virtual void compile(QSGMaterialShader *shader, QSGMaterial *material, const char *vertexCode = 0, const char *fragmentCode = 0);
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index c84e6628a5..14bc0fad07 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -104,8 +104,11 @@ char const *const *QSGTextMaskShader::attributeNames() const
}
QSGTextMaskShader::QSGTextMaskShader(QFontEngine::GlyphFormat glyphFormat)
- : QSGMaterialShader(*new QSGMaterialShaderPrivate),
- m_glyphFormat(glyphFormat)
+ : QSGMaterialShader(*new QSGMaterialShaderPrivate)
+ , m_matrix_id(-1)
+ , m_color_id(-1)
+ , m_textureScale_id(-1)
+ , m_glyphFormat(glyphFormat)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/textmask.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/textmask.frag"));
@@ -435,7 +438,9 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
{
Q_ASSERT(m_font.isValid());
QVector<QFixedPoint> fixedPointPositions;
- for (int i=0; i<glyphPositions.size(); ++i)
+ const int glyphPositionsSize = glyphPositions.size();
+ fixedPointPositions.reserve(glyphPositionsSize);
+ for (int i=0; i < glyphPositionsSize; ++i)
fixedPointPositions.append(QFixedPoint::fromPointF(glyphPositions.at(i)));
QTextureGlyphCache *cache = glyphCache();
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 7e602fc0bd..4630e45ecf 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -200,9 +200,11 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
const QVector<QPointF> positions = m_glyphs.positions();
qreal fontPixelSize = m_glyphs.rawFont().pixelSize();
- QVector<QSGGeometry::TexturedPoint2D> vp;
+ // The template parameters here are assuming that most strings are short, 64
+ // characters or less.
+ QVarLengthArray<QSGGeometry::TexturedPoint2D, 256> vp;
vp.reserve(indexes.size() * 4);
- QVector<ushort> ip;
+ QVarLengthArray<ushort, 384> ip;
ip.reserve(indexes.size() * 6);
qreal maxTexMargin = m_glyph_cache->distanceFieldRadius();
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index 422e31ad96..6f4b85a5b9 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -80,6 +80,11 @@ QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
: QSGMaterialShader(),
m_fontScale(1.0)
, m_matrixScale(1.0)
+ , m_matrix_id(-1)
+ , m_textureScale_id(-1)
+ , m_alphaMin_id(-1)
+ , m_alphaMax_id(-1)
+ , m_color_id(-1)
, m_lastAlphaMin(-1)
, m_lastAlphaMax(-1)
{
@@ -260,6 +265,7 @@ protected:
DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader()
: QSGDistanceFieldTextMaterialShader()
+ , m_styleColor_id(-1)
{
}
@@ -330,6 +336,8 @@ protected:
DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader()
: DistanceFieldStyledTextMaterialShader()
+ , m_outlineAlphaMax0_id(-1)
+ , m_outlineAlphaMax1_id(-1)
{
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldoutlinetext.frag"));
}
@@ -411,6 +419,7 @@ protected:
DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader()
: DistanceFieldStyledTextMaterialShader()
+ , m_shift_id(-1)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.frag"));
@@ -489,6 +498,8 @@ private:
QSGHiQSubPixelDistanceFieldTextMaterialShader::QSGHiQSubPixelDistanceFieldTextMaterialShader()
: QSGDistanceFieldTextMaterialShader()
+ , m_fontScale_id(-1)
+ , m_vecDelta_id(-1)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag"));
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index ec9c3c39f9..6c7fb89b6f 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -101,6 +101,22 @@ void QSGRenderLoop::cleanup()
s_instance = 0;
}
+/*!
+ * Non-threaded render loops immediately run the job if there is a context.
+ */
+void QSGRenderLoop::postJob(QQuickWindow *window, QRunnable *job)
+{
+ Q_ASSERT(window);
+ Q_ASSERT(job);
+
+ if (window->openglContext()) {
+ window->openglContext()->makeCurrent(window);
+ job->run();
+ }
+
+ delete job;
+}
+
class QSGGuiThreadRenderLoop : public QSGRenderLoop
{
Q_OBJECT
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index 4293015b96..3336731fda 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -45,6 +45,7 @@ class QQuickWindow;
class QSGContext;
class QSGRenderContext;
class QAnimationDriver;
+class QRunnable;
class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop : public QObject
{
@@ -72,6 +73,7 @@ public:
virtual QSGRenderContext *createRenderContext(QSGContext *) const = 0;
virtual void releaseResources(QQuickWindow *window) = 0;
+ virtual void postJob(QQuickWindow *window, QRunnable *job);
void addWindow(QQuickWindow *win) { m_windows.insert(win); }
void removeWindow(QQuickWindow *win) { m_windows.remove(win); }
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
deleted file mode 100644
index f1cc9d1a86..0000000000
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ /dev/null
@@ -1,655 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#define EGL_EGLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif
-
-#include "qsgshareddistancefieldglyphcache_p.h"
-
-#include <QtCore/qhash.h>
-#include <QtCore/qthread.h>
-#include <QtCore/qcoreapplication.h>
-
-#include <qpa/qplatformsharedgraphicscache.h>
-
-#include <QtQuick/qquickwindow.h>
-
-// #define QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-
- class QSGInvokeEvent: public QEvent
- {
- public:
- QSGInvokeEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId = QByteArray(),
- const QVector<quint32> &glyphIds = QVector<quint32>(),
- bool inSceneGraphUpdate = false)
- : QEvent(User)
- , m_cache(cache)
- , m_cacheId(cacheId)
- , m_glyphIds(glyphIds)
- , m_inSceneGraphUpdate(inSceneGraphUpdate)
- {}
-
- bool inSceneGraphUpdate() const { return m_inSceneGraphUpdate; }
- QPlatformSharedGraphicsCache *cache() const { return m_cache; }
-
- virtual void invoke() = 0;
- protected:
- QPlatformSharedGraphicsCache *m_cache;
- QByteArray m_cacheId;
- QVector<quint32> m_glyphIds;
- bool m_inSceneGraphUpdate;
- };
-
- class QSGReleaseItemsEvent: public QSGInvokeEvent
- {
- public:
- QSGReleaseItemsEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId,
- const QVector<quint32> &glyphIds,
- bool inSceneGraphUpdate)
- : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
- {
- }
-
- void invoke()
- {
- m_cache->releaseItems(m_cacheId, m_glyphIds);
- }
- };
-
- class QSGRequestItemsEvent: public QSGInvokeEvent
- {
- public:
- QSGRequestItemsEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId,
- const QVector<quint32> &glyphIds,
- bool inSceneGraphUpdate)
- : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
- {
- }
-
- void invoke()
- {
- m_cache->requestItems(m_cacheId, m_glyphIds);
- }
- };
-
- class QSGInsertItemsEvent: public QSGInvokeEvent
- {
- public:
- QSGInsertItemsEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId,
- const QVector<quint32> &glyphIds,
- const QVector<QImage> &images,
- bool inSceneGraphUpdate)
- : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
- , m_images(images)
- {
- }
-
- void invoke()
- {
- m_cache->insertItems(m_cacheId, m_glyphIds, m_images);
- }
-
- private:
- QVector<QImage> m_images;
- };
-
- class QSGEndRequestBatchEvent: public QSGInvokeEvent
- {
- public:
- QSGEndRequestBatchEvent(QPlatformSharedGraphicsCache *cache)
- : QSGInvokeEvent(cache)
- {
- }
-
- void invoke()
- {
- if (m_cache->requestBatchStarted())
- m_cache->endRequestBatch();
- }
- };
-
- class QSGMainThreadInvoker: public QObject
- {
- public:
- bool event(QEvent *e)
- {
- if (e->type() == QEvent::User) {
- Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
-
- QSGInvokeEvent *invokeEvent = static_cast<QSGInvokeEvent *>(e);
- if (invokeEvent->inSceneGraphUpdate()) {
- QPlatformSharedGraphicsCache *cache = invokeEvent->cache();
- if (!cache->requestBatchStarted())
- cache->beginRequestBatch();
- }
-
- static_cast<QSGInvokeEvent *>(e)->invoke();
- return true;
- }
- return QObject::event(e);
- }
-
- static QSGMainThreadInvoker *instance()
- {
- if (m_invoker == 0) {
- m_invoker = new QSGMainThreadInvoker;
- m_invoker->moveToThread(QCoreApplication::instance()->thread());
- }
-
- return m_invoker;
- }
-
- private:
- static QSGMainThreadInvoker *m_invoker;
- };
-
- QSGMainThreadInvoker* QSGMainThreadInvoker::m_invoker = 0;
-}
-
-QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
- QPlatformSharedGraphicsCache *sharedGraphicsCache,
- QSGDistanceFieldGlyphCacheManager *man,
- QOpenGLContext *c,
- const QRawFont &font)
- : QSGDistanceFieldGlyphCache(man, c, font)
- , m_cacheId(cacheId)
- , m_sharedGraphicsCache(sharedGraphicsCache)
- , m_isInSceneGraphUpdate(false)
- , m_hasPostedEvents(false)
-{
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache with id %s created in thread %p",
- cacheId.constData(), QThread::currentThreadId());
-#endif
-
- Q_ASSERT(sizeof(glyph_t) == sizeof(quint32));
- Q_ASSERT(sharedGraphicsCache != 0);
-
- connect(sharedGraphicsCache, SIGNAL(itemsMissing(QByteArray,QVector<quint32>)),
- this, SLOT(reportItemsMissing(QByteArray,QVector<quint32>)),
- Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsAvailable(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- this, SLOT(reportItemsAvailable(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsUpdated(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- this, SLOT(reportItemsUpdated(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsInvalidated(QByteArray,QVector<quint32>)),
- this, SLOT(reportItemsInvalidated(QByteArray,QVector<quint32>)),
- Qt::DirectConnection);
-
- Q_ASSERT(c);
- QQuickWindow *window = static_cast<QQuickWindow *>(c->surface());
- Q_ASSERT(window != 0);
-
- connect(window, SIGNAL(beforeSynchronizing()), this, SLOT(sceneGraphUpdateStarted()),
- Qt::DirectConnection);
- connect(window, SIGNAL(beforeRendering()), this, SLOT(sceneGraphUpdateDone()),
- Qt::DirectConnection);
-}
-
-QSGSharedDistanceFieldGlyphCache::~QSGSharedDistanceFieldGlyphCache()
-{
- {
- QHash<glyph_t, void *>::const_iterator it = m_bufferForGlyph.constBegin();
- while (it != m_bufferForGlyph.constEnd()) {
- m_sharedGraphicsCache->dereferenceBuffer(it.value());
- ++it;
- }
- }
-
- {
- QHash<quint32, PendingGlyph>::const_iterator it = m_pendingReadyGlyphs.constBegin();
- while (it != m_pendingReadyGlyphs.constEnd()) {
- m_sharedGraphicsCache->dereferenceBuffer(it.value().buffer);
- ++it;
- }
- }
-}
-
-void QSGSharedDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
-{
- typedef QSet<glyph_t>::const_iterator GlyphSetConstIt;
-
- QMutexLocker locker(&m_pendingGlyphsMutex);
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::requestGlyphs() called for %s (%d glyphs)",
- m_cacheId.constData(), glyphs.size());
-#endif
-
- m_requestedGlyphsThatHaveNotBeenReturned.unite(glyphs);
- m_requestedGlyphs.unite(glyphs);
-
- QVector<quint32> glyphsVector;
- glyphsVector.reserve(glyphs.size());
-
- for (GlyphSetConstIt it = glyphs.constBegin(), cend = glyphs.constEnd(); it != cend; ++it) {
- Q_ASSERT(!m_bufferForGlyph.contains(*it));
- glyphsVector.append(*it);
- }
-
- m_hasPostedEvents = true;
- QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(invoker, new QSGRequestItemsEvent(m_sharedGraphicsCache,
- m_cacheId,
- glyphsVector,
- m_isInSceneGraphUpdate));
-}
-
-void QSGSharedDistanceFieldGlyphCache::waitForGlyphs()
-{
- Q_ASSERT(!m_isInSceneGraphUpdate);
- if (m_isInSceneGraphUpdate) {
- qWarning("QSGSharedDistanceFieldGlyphCache::waitForGlyphs: Called from inside "
- "scenegraph update. Will freeze.");
- }
-
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- while (!m_requestedGlyphsThatHaveNotBeenReturned.isEmpty())
- m_pendingGlyphsCondition.wait(&m_pendingGlyphsMutex);
- }
-}
-
-void QSGSharedDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField> &glyphs)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::storeGlyphs() called for %s (%d glyphs)",
- m_cacheId.constData(), glyphs.size());
-#endif
-
- int glyphCount = glyphs.size();
- QVector<quint32> glyphIds(glyphCount);
- QVector<QImage> images(glyphCount);
- for (int i = 0; i < glyphs.size(); ++i) {
- const QDistanceField &df = glyphs.at(i);
- m_requestedGlyphsThatHaveNotBeenReturned.insert(df.glyph());
- glyphIds[i] = df.glyph();
- // ### TODO: Handle QDistanceField in QPlatformSharedGraphicsCache
- images[i] = df.toImage(QImage::Format_Indexed8);
- }
-
- m_hasPostedEvents = true;
- QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(invoker, new QSGInsertItemsEvent(m_sharedGraphicsCache,
- m_cacheId,
- glyphIds,
- images,
- m_isInSceneGraphUpdate));
- }
-
- processPendingGlyphs();
-}
-
-void QSGSharedDistanceFieldGlyphCache::referenceGlyphs(const QSet<glyph_t> &glyphs)
-{
- Q_UNUSED(glyphs);
-
- // Intentionally empty. Not required in this implementation, since the glyphs are reference
- // counted outside and releaseGlyphs() will only be called when there are no more references.
-}
-
-void QSGSharedDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs)
-{
- typedef QSet<glyph_t>::const_iterator GlyphSetConstIt;
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::releaseGlyphs() called for %s (%d glyphs)",
- m_cacheId.constData(), glyphs.size());
-#endif
-
- m_requestedGlyphs.subtract(glyphs);
-
- QVector<quint32> glyphsVector;
- glyphsVector.reserve(glyphs.size());
-
- for (GlyphSetConstIt glyphsIt = glyphs.constBegin(), cend = glyphs.constEnd(); glyphsIt != cend; ++glyphsIt) {
- QHash<glyph_t, void *>::iterator bufferIt = m_bufferForGlyph.find(*glyphsIt);
- if (bufferIt != m_bufferForGlyph.end()) {
- void *buffer = bufferIt.value();
- removeGlyph(*glyphsIt);
- m_bufferForGlyph.erase(bufferIt);
- Q_ASSERT(!m_bufferForGlyph.contains(*glyphsIt));
-
- if (!m_sharedGraphicsCache->dereferenceBuffer(buffer)) {
-#if !defined(QT_NO_DEBUG)
- bufferIt = m_bufferForGlyph.begin();
- while (bufferIt != m_bufferForGlyph.end()) {
- Q_ASSERT(bufferIt.value() != buffer);
- ++bufferIt;
- }
-#endif
- }
- }
-
- glyphsVector.append(*glyphsIt);
- }
-
- m_hasPostedEvents = true;
- QSGMainThreadInvoker *mainThreadInvoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(mainThreadInvoker, new QSGReleaseItemsEvent(m_sharedGraphicsCache,
- m_cacheId,
- glyphsVector,
- m_isInSceneGraphUpdate));
-}
-
-void QSGSharedDistanceFieldGlyphCache::registerOwnerElement(QQuickItem *ownerElement)
-{
- Owner &owner = m_registeredOwners[ownerElement];
- if (owner.ref == 0) {
- owner.item = ownerElement;
-
- bool ok = connect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
- Q_ASSERT_X(ok, Q_FUNC_INFO, "QML element that owns a glyph node must have triggerPreprocess() slot");
- Q_UNUSED(ok);
- }
- ++owner.ref;
-}
-
-void QSGSharedDistanceFieldGlyphCache::unregisterOwnerElement(QQuickItem *ownerElement)
-{
- QHash<QQuickItem *, Owner>::iterator it = m_registeredOwners.find(ownerElement);
- if (it != m_registeredOwners.end() && --it->ref <= 0) {
- if (it->item)
- disconnect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
- m_registeredOwners.erase(it);
- }
-}
-
-namespace {
- struct TextureContent {
- QSize size;
- QVector<glyph_t> glyphs;
- };
-}
-
-void QSGSharedDistanceFieldGlyphCache::processPendingGlyphs()
-{
- Q_ASSERT(QThread::currentThread() == thread());
-
- waitForGlyphs();
-
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_pendingMissingGlyphs.isEmpty()
- && m_pendingReadyGlyphs.isEmpty()
- && m_pendingInvalidatedGlyphs.isEmpty()) {
- return;
- }
-
- {
- QVector<glyph_t> pendingMissingGlyphs;
- pendingMissingGlyphs.reserve(m_pendingMissingGlyphs.size());
-
- QSet<glyph_t>::const_iterator it = m_pendingMissingGlyphs.constBegin();
- while (it != m_pendingMissingGlyphs.constEnd()) {
- pendingMissingGlyphs.append(*it);
- ++it;
- }
-
- markGlyphsToRender(pendingMissingGlyphs);
- }
-
- {
- QVector<glyph_t> filteredPendingInvalidatedGlyphs;
- filteredPendingInvalidatedGlyphs.reserve(m_pendingInvalidatedGlyphs.size());
-
- QSet<glyph_t>::const_iterator it = m_pendingInvalidatedGlyphs.constBegin();
- while (it != m_pendingInvalidatedGlyphs.constEnd()) {
- bool rerequestGlyph = false;
-
- // The glyph was invalidated right after being posted as ready, we throw away
- // the ready glyph and rerequest it to be certain
- QHash<quint32, PendingGlyph>::iterator pendingGlyphIt = m_pendingReadyGlyphs.find(*it);
- if (pendingGlyphIt != m_pendingReadyGlyphs.end()) {
- m_sharedGraphicsCache->dereferenceBuffer(pendingGlyphIt.value().buffer);
- pendingGlyphIt = m_pendingReadyGlyphs.erase(pendingGlyphIt);
- rerequestGlyph = true;
- }
-
- void *bufferId = m_bufferForGlyph.value(*it, 0);
- if (bufferId != 0) {
- m_sharedGraphicsCache->dereferenceBuffer(bufferId);
- m_bufferForGlyph.remove(*it);
- rerequestGlyph = true;
- }
-
- if (rerequestGlyph)
- filteredPendingInvalidatedGlyphs.append(*it);
-
- ++it;
- }
-
- // If this cache is still using the glyphs, reset the texture held by them, and mark them
- // to be rendered again since they are still needed.
- if (!filteredPendingInvalidatedGlyphs.isEmpty()) {
- setGlyphsTexture(filteredPendingInvalidatedGlyphs, Texture());
- markGlyphsToRender(filteredPendingInvalidatedGlyphs);
- }
- }
-
- {
- QList<GlyphPosition> glyphPositions;
-
- QHash<void *, TextureContent> textureContentForBuffer;
- {
- QHash<quint32, PendingGlyph>::iterator it = m_pendingReadyGlyphs.begin();
- while (it != m_pendingReadyGlyphs.end()) {
- void *currentGlyphBuffer = m_bufferForGlyph.value(it.key(), 0);
- if (currentGlyphBuffer != 0) {
- if (!m_sharedGraphicsCache->dereferenceBuffer(currentGlyphBuffer)) {
- Q_ASSERT(!textureContentForBuffer.contains(currentGlyphBuffer));
- }
- }
-
- PendingGlyph &pendingGlyph = it.value();
-
- // We don't ref or deref the buffer here, since it was already referenced when
- // added to the pending ready glyphs
- m_bufferForGlyph[it.key()] = pendingGlyph.buffer;
-
- textureContentForBuffer[pendingGlyph.buffer].size = pendingGlyph.bufferSize;
- textureContentForBuffer[pendingGlyph.buffer].glyphs.append(it.key());
-
- GlyphPosition glyphPosition;
- glyphPosition.glyph = it.key();
- glyphPosition.position = pendingGlyph.position;
-
- glyphPositions.append(glyphPosition);
-
- ++it;
- }
- }
-
- setGlyphsPosition(glyphPositions);
-
- {
- QHash<void *, TextureContent>::const_iterator it = textureContentForBuffer.constBegin();
- while (it != textureContentForBuffer.constEnd()) {
- Texture texture;
- texture.textureId = m_sharedGraphicsCache->textureIdForBuffer(it.key());
- texture.size = m_sharedGraphicsCache->sizeOfBuffer(it.key());
-
- setGlyphsTexture(it.value().glyphs, texture);
-
- ++it;
- }
- }
- }
-
- m_pendingMissingGlyphs.clear();
- m_pendingInvalidatedGlyphs.clear();
- m_pendingReadyGlyphs.clear();
- }
-}
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsAvailable(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions)
-{
- bool requestedItemsInList = false;
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsAvailable() called for %s (%d glyphs)",
- cacheId.constData(), itemIds.size());
-#endif
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphsThatHaveNotBeenReturned.contains(itemIds.at(i))) {
- requestedItemsInList = true;
- break;
- }
- }
- }
-
- if (requestedItemsInList)
- reportItemsUpdated(cacheId, bufferId,itemIds, positions);
-}
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsUpdated(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
- Q_ASSERT(itemIds.size() == positions.size());
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsUpdated() called for %s (%d glyphs)",
- cacheId.constData(), itemIds.size());
-#endif
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphs.contains(itemIds.at(i))) {
- PendingGlyph &pendingGlyph = m_pendingReadyGlyphs[itemIds.at(i)];
- void *oldBuffer = pendingGlyph.buffer;
-
- pendingGlyph.buffer = bufferId;
- pendingGlyph.position = positions.at(i);
-
- m_sharedGraphicsCache->referenceBuffer(bufferId);
- if (oldBuffer != 0)
- m_sharedGraphicsCache->dereferenceBuffer(oldBuffer);
-
- m_requestedGlyphsThatHaveNotBeenReturned.remove(itemIds.at(i));
- }
- }
- }
-
- m_pendingGlyphsCondition.wakeAll();
- emit glyphsPending();
-}
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsInvalidated(const QByteArray &cacheId,
- const QVector<quint32> &itemIds)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphs.contains(itemIds.at(i)))
- m_pendingInvalidatedGlyphs.insert(itemIds.at(i));
- }
- }
-
- emit glyphsPending();
-}
-
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsMissing(const QByteArray &cacheId,
- const QVector<quint32> &itemIds)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsMissing() called for %s (%d glyphs)",
- cacheId.constData(), itemIds.size());
-#endif
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphsThatHaveNotBeenReturned.remove(itemIds.at(i)))
- m_pendingMissingGlyphs.insert(itemIds.at(i));
- }
- }
-
- m_pendingGlyphsCondition.wakeAll();
- emit glyphsPending();
-}
-
-void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateStarted()
-{
- m_isInSceneGraphUpdate = true;
- m_hasPostedEvents = false;
-}
-
-void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateDone()
-{
- m_isInSceneGraphUpdate = false;
-
- if (m_hasPostedEvents) {
- QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(invoker, new QSGEndRequestBatchEvent(m_sharedGraphicsCache));
- m_hasPostedEvents = false;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
deleted file mode 100644
index aee77c49c6..0000000000
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSGSHAREDDISTANCEFIELDGLYPHCACHE_H
-#define QSGSHAREDDISTANCEFIELDGLYPHCACHE_H
-
-#include <QtCore/qwaitcondition.h>
-#include <private/qsgadaptationlayer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QPlatformSharedGraphicsCache;
-class QSGSharedDistanceFieldGlyphCache : public QObject, public QSGDistanceFieldGlyphCache
-{
- Q_OBJECT
-public:
- explicit QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
- QPlatformSharedGraphicsCache *sharedGraphicsCache,
- QSGDistanceFieldGlyphCacheManager *man,
- QOpenGLContext *c,
- const QRawFont &font);
- ~QSGSharedDistanceFieldGlyphCache();
-
- void registerOwnerElement(QQuickItem *ownerElement);
- void unregisterOwnerElement(QQuickItem *ownerElement);
- void processPendingGlyphs();
-
- void requestGlyphs(const QSet<glyph_t> &glyphs);
- void referenceGlyphs(const QSet<glyph_t> &glyphs);
- void storeGlyphs(const QList<QDistanceField> &glyphs);
- void releaseGlyphs(const QSet<glyph_t> &glyphs);
-
-Q_SIGNALS:
- void glyphsPending();
-
-private Q_SLOTS:
- void reportItemsMissing(const QByteArray &cacheId, const QVector<quint32> &itemIds);
- void reportItemsAvailable(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions);
- void reportItemsUpdated(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions);
- void reportItemsInvalidated(const QByteArray &cacheId, const QVector<quint32> &itemIds);
-
- void sceneGraphUpdateStarted();
- void sceneGraphUpdateDone();
-
-private:
- void waitForGlyphs();
- void saveTexture(GLuint textureId, int width, int height);
-
- QSet<quint32> m_requestedGlyphsThatHaveNotBeenReturned;
- QSet<quint32> m_requestedGlyphs;
- QWaitCondition m_pendingGlyphsCondition;
- QByteArray m_cacheId;
- QPlatformSharedGraphicsCache *m_sharedGraphicsCache;
- QMutex m_pendingGlyphsMutex;
-
- QSet<glyph_t> m_pendingInvalidatedGlyphs;
- QSet<glyph_t> m_pendingMissingGlyphs;
-
- struct PendingGlyph
- {
- PendingGlyph() : buffer(0) {}
-
- void *buffer;
- QSize bufferSize;
- QPoint position;
- };
-
- struct Owner
- {
- Owner() : ref(0) {}
- Owner(const Owner &o) : item(o.item), ref(o.ref) {}
- Owner &operator =(const Owner &o) { item = o.item; ref = o.ref; return *this; }
-
- QPointer<QQuickItem> item;
- int ref;
- };
-
- QHash<quint32, PendingGlyph> m_pendingReadyGlyphs;
- QHash<glyph_t, void *> m_bufferForGlyph;
- QHash<QQuickItem *, Owner> m_registeredOwners;
-
- bool m_isInSceneGraphUpdate;
- bool m_hasPostedEvents;
-};
-
-QT_END_NAMESPACE
-
-#endif // QSGSHAREDDISTANCEFIELDGLYPHCACHE_H
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 56637387df..3b8fdebeed 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -147,6 +147,9 @@ const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4);
// called.
const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5);
+// Passed by the window when there is a render job to run
+const QEvent::Type WM_PostJob = QEvent::Type(QEvent::User + 6);
+
template <typename T> T *windowFor(const QList<T> &list, QQuickWindow *window)
{
for (int i=0; i<list.size(); ++i) {
@@ -200,6 +203,14 @@ public:
QImage *image;
};
+class WMJobEvent : public WMWindowEvent
+{
+public:
+ WMJobEvent(QQuickWindow *c, QRunnable *postedJob)
+ : WMWindowEvent(c, WM_PostJob), job(postedJob) {}
+ ~WMJobEvent() { delete job; }
+ QRunnable *job;
+};
class QSGRenderThreadEventQueue : public QQueue<QEvent *>
{
@@ -345,7 +356,6 @@ bool QSGRenderThread::event(QEvent *e)
if (window) {
QQuickWindowPrivate::get(window)->fireAboutToStop();
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window removed";
- gl->doneCurrent();
window = 0;
}
waitCondition.wakeOne();
@@ -396,20 +406,21 @@ bool QSGRenderThread::event(QEvent *e)
case WM_Grab: {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Grab";
WMGrabEvent *ce = static_cast<WMGrabEvent *>(e);
- Q_ASSERT(ce->window == window);
+ Q_ASSERT(ce->window);
+ Q_ASSERT(ce->window == window || !window);
mutex.lock();
- if (window) {
- gl->makeCurrent(window);
+ if (ce->window) {
+ gl->makeCurrent(ce->window);
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync scene graph";
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(ce->window);
d->syncSceneGraph();
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering scene graph";
- QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize);
+ QQuickWindowPrivate::get(ce->window)->renderSceneGraph(ce->window->size());
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- grabbing result";
- *ce->image = qt_gl_read_framebuffer(windowSize * window->effectiveDevicePixelRatio(), false, false);
+ *ce->image = qt_gl_read_framebuffer(windowSize * ce->window->effectiveDevicePixelRatio(), false, false);
}
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- waking gui to handle result";
waitCondition.wakeOne();
@@ -417,6 +428,20 @@ bool QSGRenderThread::event(QEvent *e)
return true;
}
+ case WM_PostJob: {
+ qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_PostJob";
+ WMJobEvent *ce = static_cast<WMJobEvent *>(e);
+ Q_ASSERT(ce->window == window);
+ if (window) {
+ gl->makeCurrent(window);
+ ce->job->run();
+ delete ce->job;
+ ce->job = 0;
+ qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- job done";
+ }
+ return true;
+ }
+
case WM_RequestRepaint:
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestPaint";
// When GUI posts this event, it is followed by a polishAndSync, so we mustn't
@@ -990,20 +1015,20 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w)
if (!QCoreApplication::instance())
return;
+ if (!w || !w->thread->isRunning())
+ return;
+
QThread *current = QThread::currentThread();
if (current != QCoreApplication::instance()->thread() && (current != w->thread || !m_lockedForSync)) {
qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()";
return;
}
- if (!w || !w->thread->isRunning()) {
- return;
- }
qCDebug(QSG_LOG_RENDERLOOP) << "update from item" << w->window;
// Call this function from the Gui thread later as startTimer cannot be
// called from the render thread.
- if (QThread::currentThread() == w->thread) {
+ if (current == w->thread) {
qCDebug(QSG_LOG_RENDERLOOP) << "- on render thread";
w->updateDuringSync = true;
return;
@@ -1239,6 +1264,18 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window)
return result;
}
+/*!
+ * Posts a new job event to the render thread.
+ * Returns true if posting succeeded.
+ */
+void QSGThreadedRenderLoop::postJob(QQuickWindow *window, QRunnable *job)
+{
+ Window *w = windowFor(m_windows, window);
+ if (w && w->thread && w->thread->window)
+ w->thread->postEvent(new WMJobEvent(window, job));
+ else
+ delete job;
+}
#include "qsgthreadedrenderloop.moc"
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
index d5ffbf10a3..67df9dcd31 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h
+++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
@@ -71,6 +71,7 @@ public:
void releaseResources(QQuickWindow *window);
bool event(QEvent *);
+ void postJob(QQuickWindow *window, QRunnable *job);
bool interleaveIncubation() const;
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 480ac5e569..84cc2ba135 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -79,7 +79,6 @@ HEADERS += \
$$PWD/qsgdefaultglyphnode_p_p.h \
$$PWD/qsgdefaultimagenode_p.h \
$$PWD/qsgdefaultrectanglenode_p.h \
- $$PWD/qsgshareddistancefieldglyphcache_p.h \
$$PWD/qsgrenderloop_p.h \
$$PWD/qsgthreadedrenderloop_p.h \
$$PWD/qsgwindowsrenderloop_p.h \
@@ -96,7 +95,6 @@ SOURCES += \
$$PWD/qsgdistancefieldglyphnode_p.cpp \
$$PWD/qsgdefaultimagenode.cpp \
$$PWD/qsgdefaultrectanglenode.cpp \
- $$PWD/qsgshareddistancefieldglyphcache.cpp \
$$PWD/qsgrenderloop.cpp \
$$PWD/qsgthreadedrenderloop.cpp \
$$PWD/qsgwindowsrenderloop.cpp \
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index b862fa6a2b..8c649fb6bd 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -112,13 +112,15 @@ void Manager::invalidate()
}
}
-QSGTexture *Manager::create(const QImage &image)
+QSGTexture *Manager::create(const QImage &image, bool hasAlphaChannel)
{
- QSGTexture *t = 0;
+ Texture *t = 0;
if (image.width() < m_atlas_size_limit && image.height() < m_atlas_size_limit) {
if (!m_atlas)
m_atlas = new Atlas(m_atlas_size);
t = m_atlas->create(image);
+ if (!hasAlphaChannel && t->hasAlphaChannel())
+ t->setHasAlphaChannel(false);
}
return t;
}
diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h
index 399d5fd669..c0f6ab912d 100644
--- a/src/quick/scenegraph/util/qsgatlastexture_p.h
+++ b/src/quick/scenegraph/util/qsgatlastexture_p.h
@@ -58,7 +58,7 @@ public:
Manager();
~Manager();
- QSGTexture *create(const QImage &image);
+ QSGTexture *create(const QImage &image, bool hasAlphaChannel);
void invalidate();
private:
@@ -114,6 +114,7 @@ public:
int textureId() const { return m_atlas->textureId(); }
QSize textureSize() const { return atlasSubRectWithoutPadding().size(); }
+ void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
bool hasAlphaChannel() const { return m_has_alpha; }
bool hasMipmaps() const { return false; }
bool isAtlasTexture() const { return true; }
diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp
index c0ddf25765..8622f8edc1 100644
--- a/src/quick/scenegraph/util/qsgengine.cpp
+++ b/src/quick/scenegraph/util/qsgengine.cpp
@@ -150,7 +150,7 @@ QSGAbstractRenderer *QSGEngine::createRenderer() const
/*!
Creates a texture using the data of \a image
- Valid \a options are TextureCanUseAtlas
+ Valid \a options are TextureCanUseAtlas and TextureIsOpaque.
The caller takes ownership of the texture and the
texture should only be used with this engine.
@@ -160,13 +160,12 @@ QSGAbstractRenderer *QSGEngine::createRenderer() const
QSGTexture *QSGEngine::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
{
Q_D(const QSGEngine);
- if (!d->sgRenderContext->isValid())
- return 0;
-
- if (options & TextureCanUseAtlas)
- return d->sgRenderContext->createTexture(image);
- else
- return d->sgRenderContext->createTextureNoAtlas(image);
+ if (!d->sgRenderContext->isValid())
+ return 0;
+ uint flags = 0;
+ if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
+ if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
+ return d->sgRenderContext->createTexture(image, flags);
}
/*!
diff --git a/src/quick/scenegraph/util/qsgengine.h b/src/quick/scenegraph/util/qsgengine.h
index 9a74a02aa1..325d3a9ca2 100644
--- a/src/quick/scenegraph/util/qsgengine.h
+++ b/src/quick/scenegraph/util/qsgengine.h
@@ -52,7 +52,8 @@ public:
enum CreateTextureOption {
TextureHasAlphaChannel = 0x0001,
TextureOwnsGLTexture = 0x0004,
- TextureCanUseAtlas = 0x0008
+ TextureCanUseAtlas = 0x0008,
+ TextureIsOpaque = 0x0010
};
Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h
index 0f6224a831..c4d5cd20cd 100644
--- a/src/quick/util/qquickanimation_p.h
+++ b/src/quick/util/qquickanimation_p.h
@@ -57,7 +57,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimation : public QObject, public QQ
Q_INTERFACES(QQmlParserStatus)
Q_INTERFACES(QQmlPropertyValueSource)
- Q_ENUMS(Loops)
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged)
@@ -75,6 +74,7 @@ public:
virtual ~QQuickAbstractAnimation();
enum Loops { Infinite = -2 };
+ Q_ENUM(Loops)
bool isRunning() const;
void setRunning(bool);
@@ -367,7 +367,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimation : public QQuickPropertyAnim
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickRotationAnimation)
- Q_ENUMS(RotationDirection)
Q_PROPERTY(qreal from READ from WRITE setFrom)
Q_PROPERTY(qreal to READ to WRITE setTo)
@@ -384,6 +383,7 @@ public:
void setTo(qreal);
enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+ Q_ENUM(RotationDirection)
RotationDirection direction() const;
void setDirection(RotationDirection direction);
diff --git a/src/quick/util/qquickanimation_p_p.h b/src/quick/util/qquickanimation_p_p.h
index 4224c6d9ed..b40e198cc1 100644
--- a/src/quick/util/qquickanimation_p_p.h
+++ b/src/quick/util/qquickanimation_p_p.h
@@ -164,7 +164,7 @@ private:
T *m_instance;
};
-class QQuickAbstractAnimationPrivate : public QObjectPrivate, public QAnimationJobChangeListener
+class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimationPrivate : public QObjectPrivate, public QAnimationJobChangeListener
{
Q_DECLARE_PUBLIC(QQuickAbstractAnimation)
public:
diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h
index 4d3a8e9e4f..7647e582b8 100644
--- a/src/quick/util/qquickanimator_p.h
+++ b/src/quick/util/qquickanimator_p.h
@@ -136,10 +136,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimator : public QQuickAnimator
Q_DECLARE_PRIVATE(QQuickRotationAnimator)
Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
- Q_ENUMS(RotationDirection)
-
public:
enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+ Q_ENUM(RotationDirection)
QQuickRotationAnimator(QObject *parent = 0);
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 8b617e5e3f..016f41d436 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -126,9 +126,8 @@ void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState,
m_controller->startJob(this, m_job);
} else if (newState == Stopped) {
syncBackCurrentValues();
- if (m_internalState == State_Starting)
- m_internalState = State_Stopped;
- else if (m_controller) {
+ m_internalState = State_Stopped;
+ if (m_controller) {
m_controller->stopJob(this, m_job);
}
}
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index 1cffae17db..34c106e89b 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -151,7 +151,6 @@ protected:
int m_duration;
- uint m_feedback : 1;
uint m_isTransform : 1;
uint m_isUniform : 1;
uint m_hasBeenRunning : 1;
diff --git a/src/quick/util/qquickfontloader_p.h b/src/quick/util/qquickfontloader_p.h
index b6ca0b3c94..507d0210ee 100644
--- a/src/quick/util/qquickfontloader_p.h
+++ b/src/quick/util/qquickfontloader_p.h
@@ -46,7 +46,6 @@ class Q_AUTOTEST_EXPORT QQuickFontLoader : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickFontLoader)
- Q_ENUMS(Status)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
@@ -54,6 +53,7 @@ class Q_AUTOTEST_EXPORT QQuickFontLoader : public QObject
public:
enum Status { Null = 0, Ready, Loading, Error };
+ Q_ENUM(Status)
QQuickFontLoader(QObject *parent = 0);
~QQuickFontLoader();
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index a231209cd0..70fc3a0973 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -33,6 +33,9 @@
#include "qquickimageprovider.h"
+#include "qquickpixmapcache_p.h"
+#include <QtQuick/private/qsgcontext_p.h>
+
QT_BEGIN_NAMESPACE
class QQuickImageProviderPrivate
@@ -95,6 +98,23 @@ QImage QQuickTextureFactory::image() const
return QImage();
}
+/*!
+ Returns a QQuickTextureFactory holding given the image.
+
+ \since 5.6
+ */
+
+QQuickTextureFactory *QQuickTextureFactory::textureFactoryForImage(const QImage &image)
+{
+ if (image.isNull())
+ return 0;
+ QQuickTextureFactory *texture = QSGContext::createTextureFactoryFromImage(image);
+ if (texture)
+ return texture;
+ return new QQuickDefaultTextureFactory(image);
+}
+
+
/*!
\fn QSGTexture *QQuickTextureFactory::createTexture(QQuickWindow *window) const
@@ -118,6 +138,67 @@ QImage QQuickTextureFactory::image() const
/*!
+ \class QQuickImageResponse
+ \since 5.6
+ \brief The QQuickImageResponse class provides an interface for asynchronous image loading in QQuickAsyncImageProvider.
+ \inmodule QtQuick
+
+ The purpose of an image response is to provide a way for image provider jobs to be executed
+ in an asynchronous way.
+
+ Responses are deleted via \l deleteLater once the finished() signal has been emitted.
+ If you are using QRunnable as base for your QQuickImageResponse
+ ensure automatic deletion is disabled.
+
+ \sa QQuickImageProvider
+*/
+
+/*!
+ Constructs the image response
+*/
+QQuickImageResponse::QQuickImageResponse()
+{
+}
+
+/*!
+ Destructs the image response
+*/
+QQuickImageResponse::~QQuickImageResponse()
+{
+}
+
+/*!
+ Returns the error string for the job execution. An empty string means no error.
+*/
+QString QQuickImageResponse::errorString() const
+{
+ return QString();
+}
+
+/*!
+ This method is used to communicate that the response is no longer required by the engine.
+
+ It may be reimplemented to cancel a request in the provider side, however, it is not mandatory.
+*/
+void QQuickImageResponse::cancel()
+{
+}
+
+/*!
+ \fn void QQuickImageResponse::finished()
+
+ Signals that the job execution has finished (be it successfully, because an error happened or because it was cancelled).
+ */
+
+/*!
+ \fn QQuickTextureFactory *QQuickImageResponse::textureFactory() const
+
+ Returns the texture factory the job. You can use QQuickTextureFactory::textureFactoryForImage
+ if your provider works with QImage
+ */
+
+
+/*!
\class QQuickImageProvider
\since 5.0
\inmodule QtQuick
@@ -213,7 +294,7 @@ QImage QQuickTextureFactory::image() const
To force asynchronous image loading, even for image sources that do not
have the \c asynchronous property set to \c true, you may pass the
- \c QQuickImageProvider::ForceAsynchronousImageLoading flag to the image
+ \c QQmlImageProviderBase::ForceAsynchronousImageLoading flag to the image
provider constructor. This ensures that all image requests for the
provider are handled in a separate thread.
@@ -223,6 +304,12 @@ QImage QQuickTextureFactory::image() const
if \l {Image::}{asynchronous} is set to \c true, the value is ignored
and the image is loaded synchronously.
+ Asynchronous image loading for providers of type other than ImageResponse are
+ executed on a single thread per engine basis. That means that a slow image provider
+ will block the loading of any other request. To avoid that we suggest using QQuickAsyncImageProvider
+ and implement threading on the provider side via a \c QThreadPool or similar.
+ See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
+
\section2 Image caching
@@ -365,5 +452,41 @@ QQuickTextureFactory *QQuickImageProvider::requestTexture(const QString &id, QSi
return 0;
}
+/*!
+ \class QQuickAsyncImageProvider
+ \since 5.6
+ \inmodule QtQuick
+ \brief The QQuickAsyncImageProvider class provides an interface for for asynchronous control of QML image requests.
+
+ \sa QQuickImageProvider
+*/
+QQuickAsyncImageProvider::QQuickAsyncImageProvider()
+ : QQuickImageProvider(ImageResponse, ForceAsynchronousImageLoading)
+ , d(0) // just as a placeholder in case we need it for the future
+{
+ Q_UNUSED(d);
+}
+
+QQuickAsyncImageProvider::~QQuickAsyncImageProvider()
+{
+}
+
+/*!
+ \fn QQuickImageResponse *QQuickAsyncImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
+
+ Implement this method to return the job that will provide the texture with \a id.
+
+ The \a id is the requested image source, with the "image:" scheme and
+ provider identifier removed. For example, if the image \l{Image::}{source}
+ was "image://myprovider/icons/home", the given \a id would be "icons/home".
+
+ The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
+ an Image item. If \a requestedSize is a valid size, the image
+ returned should be of that size.
+
+ \note this method may be called by multiple threads, so ensure the
+ implementation of this method is reentrant.
+*/
+
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickimageprovider.h b/src/quick/util/qquickimageprovider.h
index a2b510f606..cc03eb0fa0 100644
--- a/src/quick/util/qquickimageprovider.h
+++ b/src/quick/util/qquickimageprovider.h
@@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
class QQuickImageProviderPrivate;
+class QQuickAsyncImageProviderPrivate;
class QSGTexture;
class QQuickWindow;
@@ -56,6 +57,25 @@ public:
virtual QSize textureSize() const = 0;
virtual int textureByteCount() const = 0;
virtual QImage image() const;
+
+ static QQuickTextureFactory *textureFactoryForImage(const QImage &image);
+};
+
+class Q_QUICK_EXPORT QQuickImageResponse : public QObject
+{
+Q_OBJECT
+public:
+ QQuickImageResponse();
+ virtual ~QQuickImageResponse();
+
+ virtual QQuickTextureFactory *textureFactory() const = 0;
+ virtual QString errorString() const;
+
+public Q_SLOTS:
+ virtual void cancel();
+
+Q_SIGNALS:
+ void finished();
};
class Q_QUICK_EXPORT QQuickImageProvider : public QQmlImageProviderBase
@@ -81,6 +101,18 @@ private:
QQuickImageProviderPrivate *d;
};
+class Q_QUICK_EXPORT QQuickAsyncImageProvider : public QQuickImageProvider
+{
+public:
+ QQuickAsyncImageProvider();
+ virtual ~QQuickAsyncImageProvider();
+
+ virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) = 0;
+
+private:
+ QQuickAsyncImageProviderPrivate *d;
+};
+
QT_END_NAMESPACE
#endif // QQUICKIMAGEPROVIDER_H
diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h
index eea313eeb1..5230a3cdea 100644
--- a/src/quick/util/qquickpath_p.h
+++ b/src/quick/util/qquickpath_p.h
@@ -265,7 +265,7 @@ public:
: QQuickCurve(parent), _radiusX(0), _radiusY(0), _useLargeArc(false), _direction(Clockwise) {}
enum ArcDirection { Clockwise, Counterclockwise };
- Q_ENUMS(ArcDirection)
+ Q_ENUM(ArcDirection)
qreal radiusX() const;
void setRadiusX(qreal);
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index ddf2ae2393..f36d06d00d 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -44,7 +44,6 @@
#include <qpa/qplatformintegration.h>
#include <QtQuick/private/qsgtexture_p.h>
-#include <QtQuick/private/qsgcontext_p.h>
#include <QQuickWindow>
#include <QCoreApplication>
@@ -67,7 +66,7 @@
#include <private/qquickprofiler_p.h>
-#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
+#define IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT 8
#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
#define CACHE_EXPIRE_TIME 30
#define CACHE_REMOVAL_FRACTION 4
@@ -115,16 +114,6 @@ QSGTexture *QQuickDefaultTextureFactory::createTexture(QQuickWindow *window) con
return t;
}
-static QQuickTextureFactory *textureFactoryForImage(const QImage &image)
-{
- if (image.isNull())
- return 0;
- QQuickTextureFactory *texture = QSGContext::createTextureFactoryFromImage(image);
- if (texture)
- return texture;
- return new QQuickDefaultTextureFactory(image);
-}
-
class QQuickPixmapReader;
class QQuickPixmapData;
class QQuickPixmapReply : public QObject
@@ -181,6 +170,7 @@ public:
virtual bool event(QEvent *e);
private slots:
void networkRequestDone();
+ void asyncResponseFinished();
private:
QQuickPixmapReader *reader;
};
@@ -205,8 +195,9 @@ protected:
private:
friend class QQuickPixmapReaderThreadObject;
void processJobs();
- void processJob(QQuickPixmapReply *, const QUrl &, const QSize &, AutoTransform);
+ void processJob(QQuickPixmapReply *, const QUrl &, const QString &, AutoTransform, QQuickImageProvider::ImageType, QQuickImageProvider *);
void networkRequestDone(QNetworkReply *);
+ void asyncResponseFinished(QQuickImageResponse *);
QList<QQuickPixmapReply*> jobs;
QList<QQuickPixmapReply*> cancelled;
@@ -220,7 +211,8 @@ private:
QNetworkAccessManager *networkAccessManager();
QNetworkAccessManager *accessManager;
- QHash<QNetworkReply*,QQuickPixmapReply*> replies;
+ QHash<QNetworkReply*,QQuickPixmapReply*> networkJobs;
+ QHash<QQuickImageResponse*,QQuickPixmapReply*> asyncResponses;
static int replyDownloadProgress;
static int replyFinished;
@@ -439,8 +431,8 @@ QQuickPixmapReader::~QQuickPixmapReader()
delete reply;
}
jobs.clear();
- QList<QQuickPixmapReply*> activeJobs = replies.values();
- foreach (QQuickPixmapReply *reply, activeJobs) {
+ QList<QQuickPixmapReply*> activeJobs = networkJobs.values() + asyncResponses.values();
+ foreach (QQuickPixmapReply *reply, activeJobs ) {
if (reply->loading) {
cancelled.append(reply);
reply->data = 0;
@@ -455,7 +447,7 @@ QQuickPixmapReader::~QQuickPixmapReader()
void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
{
- QQuickPixmapReply *job = replies.take(reply);
+ QQuickPixmapReply *job = networkJobs.take(reply);
if (job) {
job->redirectCount++;
@@ -472,7 +464,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress);
QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
- replies.insert(reply, job);
+ networkJobs.insert(reply, job);
return;
}
}
@@ -494,7 +486,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
// send completion event to the QQuickPixmapReply
mutex.lock();
if (!cancelled.contains(job))
- job->postReply(error, errorString, readSize, textureFactoryForImage(image));
+ job->postReply(error, errorString, readSize, QQuickTextureFactory::textureFactoryForImage(image));
mutex.unlock();
}
reply->deleteLater();
@@ -503,6 +495,32 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
threadObject->processJobs();
}
+void QQuickPixmapReader::asyncResponseFinished(QQuickImageResponse *response)
+{
+ QQuickPixmapReply *job = asyncResponses.take(response);
+
+ if (job) {
+ QQuickTextureFactory *t = 0;
+ QQuickPixmapReply::ReadError error = QQuickPixmapReply::NoError;
+ QString errorString;
+ QSize readSize;
+ if (!response->errorString().isEmpty()) {
+ error = QQuickPixmapReply::Loading;
+ errorString = response->errorString();
+ } else {
+ t = response->textureFactory();
+ }
+ mutex.lock();
+ if (!cancelled.contains(job))
+ job->postReply(error, errorString, t->textureSize(), t);
+ mutex.unlock();
+ }
+ response->deleteLater();
+
+ // kick off event loop again incase we have dropped below max request count
+ threadObject->processJobs();
+}
+
QQuickPixmapReaderThreadObject::QQuickPixmapReaderThreadObject(QQuickPixmapReader *i)
: reader(i)
{
@@ -529,6 +547,12 @@ void QQuickPixmapReaderThreadObject::networkRequestDone()
reader->networkRequestDone(reply);
}
+void QQuickPixmapReaderThreadObject::asyncResponseFinished()
+{
+ QQuickImageResponse *response = static_cast<QQuickImageResponse *>(sender());
+ reader->asyncResponseFinished(response);
+}
+
void QQuickPixmapReader::processJobs()
{
QMutexLocker locker(&mutex);
@@ -538,16 +562,22 @@ void QQuickPixmapReader::processJobs()
return; // Nothing else to do
// Clean cancelled jobs
- if (cancelled.count()) {
+ if (!cancelled.isEmpty()) {
for (int i = 0; i < cancelled.count(); ++i) {
QQuickPixmapReply *job = cancelled.at(i);
- QNetworkReply *reply = replies.key(job, 0);
+ QNetworkReply *reply = networkJobs.key(job, 0);
if (reply) {
- replies.remove(reply);
+ networkJobs.remove(reply);
if (reply->isRunning()) {
// cancel any jobs already started
reply->close();
}
+ } else {
+ QQuickImageResponse *asyncResponse = asyncResponses.key(job);
+ if (asyncResponse) {
+ asyncResponses.remove(asyncResponse);
+ asyncResponse->cancel();
+ }
}
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url));
// deleteLater, since not owned by this thread
@@ -560,27 +590,34 @@ void QQuickPixmapReader::processJobs()
// Find a job we can use
bool usableJob = false;
for (int i = jobs.count() - 1; !usableJob && i >= 0; i--) {
- QQuickPixmapReply *runningJob = jobs[i];
- const QUrl url = runningJob->url;
+ QQuickPixmapReply *job = jobs[i];
+ const QUrl url = job->url;
+ QString localFile;
+ QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
+ QQuickImageProvider *provider = 0;
if (url.scheme() == QLatin1String("image")) {
+ provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)));
+ if (provider)
+ imageType = provider->imageType();
+
usableJob = true;
} else {
- const QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
- usableJob = !localFile.isEmpty() || replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT;
+ localFile = QQmlFile::urlToLocalFileOrQrc(url);
+ usableJob = !localFile.isEmpty() || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT;
}
+
if (usableJob) {
jobs.removeAt(i);
- runningJob->loading = true;
+ job->loading = true;
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
- QSize requestSize = runningJob->requestSize;
- AutoTransform autoTransform = runningJob->autoTransform;
+ AutoTransform autoTransform = job->autoTransform;
locker.unlock();
- processJob(runningJob, url, requestSize, autoTransform);
+ processJob(job, url, localFile, autoTransform, imageType, provider);
locker.relock();
}
}
@@ -591,79 +628,97 @@ void QQuickPixmapReader::processJobs()
}
}
-void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url,
- const QSize &requestSize, AutoTransform autoTransform)
+void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, const QString &localFile,
+ AutoTransform autoTransform, QQuickImageProvider::ImageType imageType, QQuickImageProvider *provider)
{
// fetch
if (url.scheme() == QLatin1String("image")) {
// Use QQuickImageProvider
QSize readSize;
- QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
- QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)));
- if (provider)
- imageType = provider->imageType();
+ switch (imageType) {
+ case QQuickImageProvider::Invalid:
+ {
+ QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString());
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(QQuickPixmapReply::Loading, errorStr, readSize, 0);
+ mutex.unlock();
+ break;
+ }
- if (imageType == QQuickImageProvider::Invalid) {
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::Loading;
- QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString());
- QImage image;
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image));
- mutex.unlock();
- } else if (imageType == QQuickImageProvider::Image) {
- QImage image = provider->requestImage(imageId(url), &readSize, requestSize);
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
- QString errorStr;
- if (image.isNull()) {
- errorCode = QQuickPixmapReply::Loading;
- errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ case QQuickImageProvider::Image:
+ {
+ QImage image = provider->requestImage(imageId(url), &readSize, runningJob->requestSize);
+ QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
+ QString errorStr;
+ if (image.isNull()) {
+ errorCode = QQuickPixmapReply::Loading;
+ errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image));
+ mutex.unlock();
+ break;
}
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image));
- mutex.unlock();
- } else if (imageType == QQuickImageProvider::Pixmap) {
- const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize);
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
- QString errorStr;
- if (pixmap.isNull()) {
- errorCode = QQuickPixmapReply::Loading;
- errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+
+ case QQuickImageProvider::Pixmap:
+ {
+ const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, runningJob->requestSize);
+ QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
+ QString errorStr;
+ if (pixmap.isNull()) {
+ errorCode = QQuickPixmapReply::Loading;
+ errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()));
+ mutex.unlock();
+ break;
}
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(pixmap.toImage()));
- mutex.unlock();
- } else {
- QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, requestSize);
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
- QString errorStr;
- if (!t) {
- errorCode = QQuickPixmapReply::Loading;
- errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString());
+
+ case QQuickImageProvider::Texture:
+ {
+ QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, runningJob->requestSize);
+ QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
+ QString errorStr;
+ if (!t) {
+ errorCode = QQuickPixmapReply::Loading;
+ errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, t);
+ else
+ delete t;
+ mutex.unlock();
+ break;
}
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, t);
- else
- delete t;
- mutex.unlock();
+ case QQuickImageProvider::ImageResponse:
+ {
+ QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider);
+ QQuickImageResponse *response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize);
+
+ QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished()));
+
+ asyncResponses.insert(response, runningJob);
+ break;
+ }
}
} else {
- QString lf = QQmlFile::urlToLocalFileOrQrc(url);
- if (!lf.isEmpty()) {
+ if (!localFile.isEmpty()) {
// Image is local - load/decode immediately
QImage image;
QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
QString errorStr;
- QFile f(lf);
+ QFile f(localFile);
QSize readSize;
if (f.open(QIODevice::ReadOnly)) {
- if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize, autoTransform))
+ if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, autoTransform))
errorCode = QQuickPixmapReply::Loading;
} else {
errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString());
@@ -671,7 +726,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
}
mutex.lock();
if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image));
+ runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image));
mutex.unlock();
} else {
// Network resource
@@ -682,7 +737,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
- replies.insert(reply, runningJob);
+ networkJobs.insert(reply, runningJob);
}
}
}
@@ -775,8 +830,6 @@ inline uint qHash(const QQuickPixmapKey &key)
return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.autoTransform * 0x5c5c5c5c);
}
-class QSGContext;
-
class QQuickPixmapStore : public QObject
{
Q_OBJECT
@@ -1084,7 +1137,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
QImage image = provider->requestImage(imageId(url), &readSize, requestSize);
if (!image.isNull()) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault);
}
}
case QQuickImageProvider::Pixmap:
@@ -1092,9 +1145,14 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize);
if (!pixmap.isNull()) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault);
}
}
+ case QQuickImageProvider::ImageResponse:
+ {
+ // Fall through, ImageResponse providers never get here
+ Q_ASSERT(imageType != QQuickImageProvider::ImageResponse && "Sync call to ImageResponse provider");
+ }
}
// provider has bad image type, or provider returned null image
@@ -1115,7 +1173,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
AutoTransform appliedTransform = autoTransform;
if (readImage(url, &f, &image, &errorString, &readSize, requestSize, appliedTransform)) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform);
}
errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString());
@@ -1252,7 +1310,7 @@ void QQuickPixmap::setImage(const QImage &p)
clear();
if (!p.isNull())
- d = new QQuickPixmapData(this, textureFactoryForImage(p));
+ d = new QQuickPixmapData(this, QQuickTextureFactory::textureFactoryForImage(p));
}
void QQuickPixmap::setPixmap(const QQuickPixmap &other)
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 6c333c6b13..58d78a5d84 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -145,12 +145,12 @@ public:
QQmlBoundSignalExpressionPointer reverseExpression;
QQmlBoundSignalExpressionPointer rewindExpression;
- virtual void execute(Reason) {
+ virtual void execute() {
QQmlPropertyPrivate::setSignalExpression(property, expression);
}
virtual bool isReversable() { return true; }
- virtual void reverse(Reason) {
+ virtual void reverse() {
QQmlPropertyPrivate::setSignalExpression(property, reverseExpression);
}
@@ -464,10 +464,10 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
// XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
// so that we can avoid creating then destroying the binding in this case.
a.toValue = newBinding->evaluate();
- newBinding->destroy();
+ delete newBinding;
} else {
newBinding->setTarget(prop);
- a.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ a.toBinding = newBinding;
a.deletableToBinding = true;
}
@@ -558,11 +558,7 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val
if (entry.name == name) {
expressionIterator.remove();
if (state() && state()->isStateActive()) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name));
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(d->property(name), 0);
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(d->property(name));
d->property(name).write(value);
}
@@ -624,15 +620,9 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
if (entry.name == name) {
entry.expression = expression;
if (state() && state()->isStateActive()) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name));
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(d->property(name), 0);
- oldBinding->destroy();
- }
-
QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this));
newBinding->setTarget(d->property(name));
- QQmlPropertyPrivate::setBinding(d->property(name), newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
}
return;
}
@@ -651,7 +641,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this));
newBinding->setTarget(d->property(name));
- QQmlPropertyPrivate::setBinding(d->property(name), newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
} else {
QQuickStateAction action;
action.restore = restoreEntryValues();
@@ -666,10 +656,10 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
// XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
// so that we can avoid creating then destroying the binding in this case.
action.toValue = newBinding->evaluate();
- newBinding->destroy();
+ delete newBinding;
} else {
- newBinding->setTarget(d->property(name));
- action.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ newBinding->setTarget(action.property);
+ action.toBinding = newBinding;
action.deletableToBinding = true;
state()->addEntryToRevertList(action);
@@ -677,7 +667,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
if (oldBinding)
oldBinding->setEnabled(false, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
- QQmlPropertyPrivate::setBinding(action.property, newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
}
}
}
diff --git a/src/quick/util/qquicksmoothedanimation_p.h b/src/quick/util/qquicksmoothedanimation_p.h
index 68479aa629..efac9217f5 100644
--- a/src/quick/util/qquicksmoothedanimation_p.h
+++ b/src/quick/util/qquicksmoothedanimation_p.h
@@ -47,7 +47,6 @@ class Q_AUTOTEST_EXPORT QQuickSmoothedAnimation : public QQuickNumberAnimation
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickSmoothedAnimation)
- Q_ENUMS(ReversingMode)
Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
@@ -55,6 +54,7 @@ class Q_AUTOTEST_EXPORT QQuickSmoothedAnimation : public QQuickNumberAnimation
public:
enum ReversingMode { Eased, Immediate, Sync };
+ Q_ENUM(ReversingMode)
QQuickSmoothedAnimation(QObject *parent = 0);
~QQuickSmoothedAnimation();
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
index 98d7a76c7e..be676680a6 100644
--- a/src/quick/util/qquickstate.cpp
+++ b/src/quick/util/qquickstate.cpp
@@ -78,7 +78,7 @@ QQuickStateActionEvent::~QQuickStateActionEvent()
{
}
-void QQuickStateActionEvent::execute(Reason)
+void QQuickStateActionEvent::execute()
{
}
@@ -87,7 +87,7 @@ bool QQuickStateActionEvent::isReversable()
return false;
}
-void QQuickStateActionEvent::reverse(Reason)
+void QQuickStateActionEvent::reverse()
{
}
@@ -157,11 +157,6 @@ QQuickState::~QQuickState()
Q_D(QQuickState);
if (d->group)
d->group->removeState(this);
-
- foreach (const QQuickSimpleAction &action, d->revertList) {
- if (action.binding())
- action.binding()->destroy();
- }
}
/*!
@@ -361,8 +356,7 @@ void QQuickState::cancel()
void QQuickStateAction::deleteFromBinding()
{
if (fromBinding) {
- QQmlPropertyPrivate::setBinding(property, 0);
- fromBinding->destroy();
+ QQmlPropertyPrivate::removeBinding(property);
fromBinding = 0;
}
}
@@ -413,9 +407,6 @@ bool QQuickState::changeBindingInRevertList(QObject *target, const QString &name
while (revertListIterator.hasNext()) {
QQuickSimpleAction &simpleAction = revertListIterator.next();
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
- if (simpleAction.binding())
- simpleAction.binding()->destroy();
-
simpleAction.setBinding(binding);
return true;
}
@@ -435,15 +426,11 @@ bool QQuickState::removeEntryFromRevertList(QObject *target, const QString &name
while (revertListIterator.hasNext()) {
QQuickSimpleAction &simpleAction = revertListIterator.next();
if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property());
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(simpleAction.property(), 0);
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(simpleAction.property());
simpleAction.property().write(simpleAction.value());
if (simpleAction.binding())
- QQmlPropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
+ QQmlPropertyPrivate::setBinding(simpleAction.binding());
revertListIterator.remove();
return true;
@@ -473,15 +460,11 @@ void QQuickState::removeAllEntriesFromRevertList(QObject *target)
while (revertListIterator.hasNext()) {
QQuickSimpleAction &simpleAction = revertListIterator.next();
if (simpleAction.property().object() == target) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property());
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(simpleAction.property(), 0);
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(simpleAction.property());
simpleAction.property().write(simpleAction.value());
if (simpleAction.binding())
- QQmlPropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
+ QQmlPropertyPrivate::setBinding(simpleAction.binding());
revertListIterator.remove();
}
@@ -494,18 +477,15 @@ void QQuickState::addEntriesToRevertList(const QList<QQuickStateAction> &actionL
Q_D(QQuickState);
if (isStateActive()) {
QList<QQuickSimpleAction> simpleActionList;
+ simpleActionList.reserve(actionList.count());
QListIterator<QQuickStateAction> actionListIterator(actionList);
while(actionListIterator.hasNext()) {
const QQuickStateAction &action = actionListIterator.next();
QQuickSimpleAction simpleAction(action);
action.property.write(action.toValue);
- if (!action.toBinding.isNull()) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property());
- if (oldBinding)
- QQmlPropertyPrivate::setBinding(simpleAction.property(), 0);
- QQmlPropertyPrivate::setBinding(simpleAction.property(), action.toBinding.data(), QQmlPropertyPrivate::DontRemoveBinding);
- }
+ if (action.toBinding)
+ QQmlPropertyPrivate::setBinding(action.toBinding.data());
simpleActionList.append(simpleAction);
}
@@ -619,7 +599,7 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
for (int jj = 0; jj < d->revertList.count(); ++jj) {
if (d->revertList.at(jj).property() == action.property) {
found = true;
- if (d->revertList.at(jj).binding() != action.fromBinding) {
+ if (d->revertList.at(jj).binding() != action.fromBinding.data()) {
action.deleteFromBinding();
}
break;
@@ -663,16 +643,13 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
}
if (!found) {
QVariant cur = d->revertList.at(ii).property().read();
- QQmlAbstractBinding *delBinding =
- QQmlPropertyPrivate::setBinding(d->revertList.at(ii).property(), 0);
- if (delBinding)
- delBinding->destroy();
+ QQmlPropertyPrivate::removeBinding(d->revertList.at(ii).property());
QQuickStateAction a;
a.property = d->revertList.at(ii).property();
a.fromValue = cur;
a.toValue = d->revertList.at(ii).value();
- a.toBinding = QQmlAbstractBinding::getPointer(d->revertList.at(ii).binding());
+ a.toBinding = d->revertList.at(ii).binding();
a.specifiedObject = d->revertList.at(ii).specifiedObject();
a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
a.event = d->revertList.at(ii).event();
diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h
index 0c774635d8..1870b70626 100644
--- a/src/quick/util/qquickstate_p.h
+++ b/src/quick/util/qquickstate_p.h
@@ -39,13 +39,14 @@
#include <QtCore/qobject.h>
#include <QtCore/qsharedpointer.h>
#include <private/qtquickglobal_p.h>
+#include <private/qqmlabstractbinding_p.h>
QT_BEGIN_NAMESPACE
class QQuickStateActionEvent;
-class QQmlAbstractBinding;
class QQmlBinding;
class QQmlExpression;
+
class QQuickStateAction
{
public:
@@ -63,8 +64,8 @@ public:
QVariant fromValue;
QVariant toValue;
- QQmlAbstractBinding *fromBinding;
- QWeakPointer<QQmlAbstractBinding> toBinding;
+ QQmlAbstractBinding::Ptr fromBinding;
+ QQmlAbstractBinding::Ptr toBinding;
QQuickStateActionEvent *event;
//strictly for matching
@@ -80,13 +81,12 @@ public:
virtual ~QQuickStateActionEvent();
enum EventType { Script, SignalHandler, ParentChange, AnchorChanges };
- enum Reason { ActualChange, FastForward };
virtual EventType type() const = 0;
- virtual void execute(Reason reason = ActualChange);
+ virtual void execute();
virtual bool isReversable();
- virtual void reverse(Reason reason = ActualChange);
+ virtual void reverse();
virtual void saveOriginals() {}
virtual bool needsCopy() { return false; }
virtual void copyOriginals(QQuickStateActionEvent *) {}
diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h
index fc589f0d2d..e6ecb424e5 100644
--- a/src/quick/util/qquickstate_p_p.h
+++ b/src/quick/util/qquickstate_p_p.h
@@ -71,7 +71,7 @@ public:
if (state == StartState) {
m_value = a.fromValue;
if (QQmlPropertyPrivate::binding(m_property)) {
- m_binding = QQmlAbstractBinding::getPointer(QQmlPropertyPrivate::binding(m_property));
+ m_binding = QQmlPropertyPrivate::binding(m_property);
}
m_reverseEvent = true;
} else {
@@ -88,7 +88,7 @@ public:
QQuickSimpleAction(const QQuickSimpleAction &other)
: m_property(other.m_property),
m_value(other.m_value),
- m_binding(QQmlAbstractBinding::getPointer(other.binding())),
+ m_binding(other.binding()),
m_specifiedObject(other.m_specifiedObject),
m_specifiedProperty(other.m_specifiedProperty),
m_event(other.m_event),
@@ -100,7 +100,7 @@ public:
{
m_property = other.m_property;
m_value = other.m_value;
- m_binding = QQmlAbstractBinding::getPointer(other.binding());
+ m_binding = other.binding();
m_specifiedObject = other.m_specifiedObject;
m_specifiedProperty = other.m_specifiedProperty;
m_event = other.m_event;
@@ -131,7 +131,7 @@ public:
void setBinding(QQmlAbstractBinding *binding)
{
- m_binding = QQmlAbstractBinding::getPointer(binding);
+ m_binding = binding;
}
QQmlAbstractBinding *binding() const
@@ -162,7 +162,7 @@ public:
private:
QQmlProperty m_property;
QVariant m_value;
- QQmlAbstractBinding::Pointer m_binding;
+ QQmlAbstractBinding::Ptr m_binding;
QObject *m_specifiedObject;
QString m_specifiedProperty;
QQuickStateActionEvent *m_event;
diff --git a/src/quick/util/qquickstatechangescript.cpp b/src/quick/util/qquickstatechangescript.cpp
index 6d25b9791d..c276183d62 100644
--- a/src/quick/util/qquickstatechangescript.cpp
+++ b/src/quick/util/qquickstatechangescript.cpp
@@ -118,7 +118,7 @@ void QQuickStateChangeScript::setName(const QString &n)
d->name = n;
}
-void QQuickStateChangeScript::execute(Reason)
+void QQuickStateChangeScript::execute()
{
Q_D(QQuickStateChangeScript);
if (!d->script.isEmpty()) {
diff --git a/src/quick/util/qquickstatechangescript_p.h b/src/quick/util/qquickstatechangescript_p.h
index 4ff6f0db3e..6c019a43d2 100644
--- a/src/quick/util/qquickstatechangescript_p.h
+++ b/src/quick/util/qquickstatechangescript_p.h
@@ -62,7 +62,7 @@ public:
QString name() const;
void setName(const QString &);
- virtual void execute(Reason reason = ActualChange);
+ virtual void execute();
};
diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp
index 5efe65ef44..6b1768e9ef 100644
--- a/src/quick/util/qquickstyledtext.cpp
+++ b/src/quick/util/qquickstyledtext.cpp
@@ -182,7 +182,7 @@ void QQuickStyledText::parse(const QString &string, QTextLayout &layout,
void QQuickStyledTextPrivate::parse()
{
- QList<QTextLayout::FormatRange> ranges;
+ QVector<QTextLayout::FormatRange> ranges;
QStack<QTextCharFormat> formatStack;
QString drawText;
@@ -283,7 +283,7 @@ void QQuickStyledTextPrivate::parse()
}
layout.setText(drawText);
- layout.setAdditionalFormats(ranges);
+ layout.setFormats(ranges);
}
void QQuickStyledTextPrivate::appendText(const QString &textIn, int start, int length, QString &textOut)
diff --git a/src/quick/util/qquicksystempalette_p.h b/src/quick/util/qquicksystempalette_p.h
index 143efa1c12..fb898eb1fa 100644
--- a/src/quick/util/qquicksystempalette_p.h
+++ b/src/quick/util/qquicksystempalette_p.h
@@ -45,7 +45,6 @@ class QQuickSystemPalettePrivate;
class Q_AUTOTEST_EXPORT QQuickSystemPalette : public QObject
{
Q_OBJECT
- Q_ENUMS(ColorGroup)
Q_DECLARE_PRIVATE(QQuickSystemPalette)
Q_PROPERTY(QQuickSystemPalette::ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY paletteChanged)
@@ -69,6 +68,7 @@ public:
~QQuickSystemPalette();
enum ColorGroup { Active = QPalette::Active, Inactive = QPalette::Inactive, Disabled = QPalette::Disabled };
+ Q_ENUM(ColorGroup)
QColor window() const;
QColor windowText() const;
diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp
index 74754a0bfb..88fc03bba8 100644
--- a/src/quick/util/qquicktimeline.cpp
+++ b/src/quick/util/qquicktimeline.cpp
@@ -659,7 +659,7 @@ void QQuickTimeLine::complete()
*/
void QQuickTimeLine::clear()
{
- for (QQuickTimeLinePrivate::Ops::const_iterator iter = d->ops.begin(), cend = d->ops.end(); iter != cend; ++iter)
+ for (QQuickTimeLinePrivate::Ops::const_iterator iter = d->ops.cbegin(), cend = d->ops.cend(); iter != cend; ++iter)
iter.key()->_t = 0;
d->ops.clear();
d->length = 0;
diff --git a/src/quick/util/qquicktransitionmanager.cpp b/src/quick/util/qquicktransitionmanager.cpp
index 832596d9a2..3992df993c 100644
--- a/src/quick/util/qquicktransitionmanager.cpp
+++ b/src/quick/util/qquicktransitionmanager.cpp
@@ -101,8 +101,8 @@ void QQuickTransitionManager::complete()
void QQuickTransitionManagerPrivate::applyBindings()
{
foreach(const QQuickStateAction &action, bindingsList) {
- if (!action.toBinding.isNull()) {
- QQmlPropertyPrivate::setBinding(action.property, action.toBinding.data());
+ if (action.toBinding) {
+ QQmlPropertyPrivate::setBinding(action.toBinding.data());
} else if (action.event) {
if (action.reverseEvent)
action.event->reverse();
@@ -131,7 +131,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
if (action.toBinding)
d->bindingsList << action;
if (action.fromBinding)
- QQmlPropertyPrivate::setBinding(action.property, 0); // Disable current binding
+ QQmlPropertyPrivate::removeBinding(action.property); // Disable current binding
if (action.event && action.event->changesBindings()) { //### assume isReversable()?
d->bindingsList << action;
action.event->clearBindings();
@@ -146,24 +146,21 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
//
// This doesn't catch everything, and it might be a little fragile in
// some cases - but whatcha going to do?
- //
- // Note that we only fast forward if both a transition and bindings are
- // present, as it is unnecessary (and potentially expensive) otherwise.
if (transition && !d->bindingsList.isEmpty()) {
// Apply all the property and binding changes
for (int ii = 0; ii < applyList.size(); ++ii) {
const QQuickStateAction &action = applyList.at(ii);
- if (!action.toBinding.isNull()) {
- QQmlPropertyPrivate::setBinding(action.property, action.toBinding.data(), QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ if (action.toBinding) {
+ QQmlPropertyPrivate::setBinding(action.toBinding.data(), QQmlPropertyPrivate::None, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
} else if (!action.event) {
QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
} else if (action.event->isReversable()) {
if (action.reverseEvent)
- action.event->reverse(QQuickStateActionEvent::FastForward);
+ action.event->reverse();
else
- action.event->execute(QQuickStateActionEvent::FastForward);
+ action.event->execute();
}
}
@@ -175,7 +172,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
continue;
}
const QQmlProperty &prop = action->property;
- if (!action->toBinding.isNull() || !action->toValue.isValid()) {
+ if (action->toBinding || !action->toValue.isValid()) {
action->toValue = prop.read();
}
}
@@ -192,7 +189,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
}
if (action.toBinding)
- QQmlPropertyPrivate::setBinding(action.property, 0); // Make sure this is disabled during the transition
+ QQmlPropertyPrivate::removeBinding(action.property); // Make sure this is disabled during the transition
QQmlPropertyPrivate::write(action.property, action.fromValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
}
@@ -269,10 +266,9 @@ void QQuickTransitionManager::cancel()
for(int i = 0; i < d->bindingsList.count(); ++i) {
QQuickStateAction action = d->bindingsList[i];
- if (!action.toBinding.isNull() && action.deletableToBinding) {
- QQmlPropertyPrivate::setBinding(action.property, 0);
- action.toBinding.data()->destroy();
- action.toBinding.clear();
+ if (action.toBinding && action.deletableToBinding) {
+ QQmlPropertyPrivate::removeBinding(action.property);
+ action.toBinding = 0;
action.deletableToBinding = false;
} else if (action.event) {
//### what do we do here?
diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp
index 4d156a2d9a..4f6e49fa7a 100644
--- a/src/quick/util/qquickutilmodule.cpp
+++ b/src/quick/util/qquickutilmodule.cpp
@@ -49,6 +49,7 @@
#include "qquicktransition_p.h"
#include "qquickanimator_p.h"
#include "qquickshortcut_p.h"
+#include "qquickvalidator_p.h"
#include <qqmlinfo.h>
#include <private/qqmltypenotavailable_p.h>
#include <private/qquickanimationcontroller_p.h>
@@ -87,6 +88,13 @@ void QQuickUtilModule::defineModule()
qmlRegisterType<QQuickTransition>("QtQuick",2,0,"Transition");
qmlRegisterType<QQuickVector3dAnimation>("QtQuick",2,0,"Vector3dAnimation");
+#ifndef QT_NO_VALIDATOR
+ qmlRegisterType<QValidator>();
+ qmlRegisterType<QQuickIntValidator>("QtQuick",2,0,"IntValidator");
+ qmlRegisterType<QQuickDoubleValidator>("QtQuick",2,0,"DoubleValidator");
+ qmlRegisterType<QRegExpValidator>("QtQuick",2,0,"RegExpValidator");
+#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");
diff --git a/src/quick/util/qquickvalidator.cpp b/src/quick/util/qquickvalidator.cpp
new file mode 100644
index 0000000000..3eebf5d77a
--- /dev/null
+++ b/src/quick/util/qquickvalidator.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickvalidator_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VALIDATOR
+
+/*!
+ \qmltype IntValidator
+ \instantiates QIntValidator
+ \inqmlmodule QtQuick
+ \ingroup qtquick-text-utility
+ \brief Defines a validator for integer values
+
+ The IntValidator type provides a validator for integer values.
+
+ If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to
+ interpret the number and will accept locale specific digits, group separators, and positive
+ and negative signs. In addition, IntValidator is always guaranteed to accept a number
+ formatted according to the "C" locale.
+*/
+
+QQuickIntValidator::QQuickIntValidator(QObject *parent)
+ : QIntValidator(parent)
+{
+}
+
+/*!
+ \qmlproperty string QtQuick::IntValidator::locale
+
+ This property holds the name of the locale used to interpret the number.
+
+ \sa {QtQml::Qt::locale()}{Qt.locale()}
+*/
+
+QString QQuickIntValidator::localeName() const
+{
+ return locale().name();
+}
+
+void QQuickIntValidator::setLocaleName(const QString &name)
+{
+ if (locale().name() != name) {
+ setLocale(QLocale(name));
+ emit localeNameChanged();
+ }
+}
+
+void QQuickIntValidator::resetLocaleName()
+{
+ QLocale defaultLocale;
+ if (locale() != defaultLocale) {
+ setLocale(defaultLocale);
+ emit localeNameChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick::IntValidator::top
+
+ This property holds the validator's highest acceptable value.
+ By default, this property's value is derived from the highest signed integer available (typically 2147483647).
+*/
+/*!
+ \qmlproperty int QtQuick::IntValidator::bottom
+
+ This property holds the validator's lowest acceptable value.
+ By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
+*/
+
+/*!
+ \qmltype DoubleValidator
+ \instantiates QDoubleValidator
+ \inqmlmodule QtQuick
+ \ingroup qtquick-text-utility
+ \brief Defines a validator for non-integer numbers
+
+ The DoubleValidator type provides a validator for non-integer numbers.
+
+ Input is accepted if it contains a double that is within the valid range
+ and is in the correct format.
+
+ Input is accepected but invalid if it contains a double that is outside
+ the range or is in the wrong format; e.g. with too many digits after the
+ decimal point or is empty.
+
+ Input is rejected if it is not a double.
+
+ Note: If the valid range consists of just positive doubles (e.g. 0.0 to
+ 100.0) and input is a negative double then it is rejected. If \l notation
+ is set to DoubleValidator.StandardNotation, and the input contains more
+ digits before the decimal point than a double in the valid range may have,
+ it is also rejected. If \l notation is DoubleValidator.ScientificNotation,
+ and the input is not in the valid range, it is accecpted but invalid. The
+ value may yet become valid by changing the exponent.
+*/
+
+QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent)
+ : QDoubleValidator(parent)
+{
+}
+
+/*!
+ \qmlproperty string QtQuick::DoubleValidator::locale
+
+ This property holds the name of the locale used to interpret the number.
+
+ \sa {QtQml::Qt::locale()}{Qt.locale()}
+*/
+
+QString QQuickDoubleValidator::localeName() const
+{
+ return locale().name();
+}
+
+void QQuickDoubleValidator::setLocaleName(const QString &name)
+{
+ if (locale().name() != name) {
+ setLocale(QLocale(name));
+ emit localeNameChanged();
+ }
+}
+
+void QQuickDoubleValidator::resetLocaleName()
+{
+ QLocale defaultLocale;
+ if (locale() != defaultLocale) {
+ setLocale(defaultLocale);
+ emit localeNameChanged();
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick::DoubleValidator::top
+
+ This property holds the validator's maximum acceptable value.
+ By default, this property contains a value of infinity.
+*/
+/*!
+ \qmlproperty real QtQuick::DoubleValidator::bottom
+
+ This property holds the validator's minimum acceptable value.
+ By default, this property contains a value of -infinity.
+*/
+/*!
+ \qmlproperty int QtQuick::DoubleValidator::decimals
+
+ This property holds the validator's maximum number of digits after the decimal point.
+ By default, this property contains a value of 1000.
+*/
+/*!
+ \qmlproperty enumeration QtQuick::DoubleValidator::notation
+ This property holds the notation of how a string can describe a number.
+
+ The possible values for this property are:
+
+ \list
+ \li DoubleValidator.StandardNotation
+ \li DoubleValidator.ScientificNotation (default)
+ \endlist
+
+ If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
+*/
+
+/*!
+ \qmltype RegExpValidator
+ \instantiates QRegExpValidator
+ \inqmlmodule QtQuick
+ \ingroup qtquick-text-utility
+ \brief Provides a string validator
+
+ The RegExpValidator type provides a validator, which counts as valid any string which
+ matches a specified regular expression.
+*/
+/*!
+ \qmlproperty regExp QtQuick::RegExpValidator::regExp
+
+ This property holds the regular expression used for validation.
+
+ Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
+ matching "a".
+
+ By default, this property contains a regular expression with the pattern .* that matches any string.
+*/
+
+#endif // QT_NO_VALIDATOR
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/util/qquickvalidator_p.h b/src/quick/util/qquickvalidator_p.h
new file mode 100644
index 0000000000..59d7884afc
--- /dev/null
+++ b/src/quick/util/qquickvalidator_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKVALIDATOR_P_H
+#define QQUICKVALIDATOR_P_H
+
+#include <QtGui/qvalidator.h>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VALIDATOR
+class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator
+{
+ Q_OBJECT
+ Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
+public:
+ QQuickIntValidator(QObject *parent = 0);
+
+ QString localeName() const;
+ void setLocaleName(const QString &name);
+ void resetLocaleName();
+
+Q_SIGNALS:
+ void localeNameChanged();
+};
+
+class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator
+{
+ Q_OBJECT
+ Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
+public:
+ QQuickDoubleValidator(QObject *parent = 0);
+
+ QString localeName() const;
+ void setLocaleName(const QString &name);
+ void resetLocaleName();
+
+Q_SIGNALS:
+ void localeNameChanged();
+};
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_VALIDATOR
+QML_DECLARE_TYPE(QValidator)
+QML_DECLARE_TYPE(QQuickIntValidator)
+QML_DECLARE_TYPE(QQuickDoubleValidator)
+QML_DECLARE_TYPE(QRegExpValidator)
+#endif
+
+#endif // QQUICKVALIDATOR_P_H
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index f62306ed01..1436d8e310 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -266,8 +266,6 @@ class QQuickFontValueType
{
QFont v;
Q_GADGET
- Q_ENUMS(FontWeight)
- Q_ENUMS(Capitalization)
Q_PROPERTY(QString family READ family WRITE setFamily FINAL)
Q_PROPERTY(bool bold READ bold WRITE setBold FINAL)
@@ -292,11 +290,13 @@ public:
Bold = QFont::Bold,
ExtraBold = QFont::ExtraBold,
Black = QFont::Black };
+ Q_ENUM(FontWeight)
enum Capitalization { MixedCase = QFont::MixedCase,
AllUppercase = QFont::AllUppercase,
AllLowercase = QFont::AllLowercase,
SmallCaps = QFont::SmallCaps,
Capitalize = QFont::Capitalize };
+ Q_ENUM(Capitalization)
Q_INVOKABLE QString toString() const;
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index 0e0df4e751..ffb31ae75e 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -29,7 +29,8 @@ SOURCES += \
$$PWD/qquickprofiler.cpp \
$$PWD/qquickfontmetrics.cpp \
$$PWD/qquicktextmetrics.cpp \
- $$PWD/qquickshortcut.cpp
+ $$PWD/qquickshortcut.cpp \
+ $$PWD/qquickvalidator.cpp
HEADERS += \
$$PWD/qquickapplication_p.h\
@@ -66,4 +67,5 @@ HEADERS += \
$$PWD/qquickprofiler_p.h \
$$PWD/qquickfontmetrics_p.h \
$$PWD/qquicktextmetrics_p.h \
- $$PWD/qquickshortcut_p.h
+ $$PWD/qquickshortcut_p.h \
+ $$PWD/qquickvalidator_p.h
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index a848774ae9..955abfddb2 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -538,6 +538,9 @@ QQuickWidget::Status QQuickWidget::status() const
if (!d->component)
return QQuickWidget::Null;
+ if (d->component->status() == QQmlComponent::Ready && !d->root)
+ return QQuickWidget::Error;
+
return QQuickWidget::Status(d->component->status());
}
@@ -559,6 +562,10 @@ QList<QQmlError> QQuickWidget::errors() const
QQmlError error;
error.setDescription(QLatin1String("QQuickWidget: invalid qml engine."));
errs << error;
+ } else if (d->component->status() == QQmlComponent::Ready && !d->root) {
+ QQmlError error;
+ error.setDescription(QLatin1String("QQuickWidget: invalid root object."));
+ errs << error;
}
return errs;
@@ -878,14 +885,15 @@ void QQuickWidgetPrivate::setRootObject(QObject *obj)
if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
root = sgItem;
sgItem->setParentItem(offscreenWindow->contentItem());
+ } else if (qobject_cast<QWindow *>(obj)) {
+ qWarning() << "QQuickWidget does not support using windows as a root item." << endl
+ << endl
+ << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl;
} else {
qWarning() << "QQuickWidget only supports loading of root objects that derive from QQuickItem." << endl
<< endl
- << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
- << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
- << endl
- << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
- << "QDeclarativeView class in the Qt Quick 1 module." << endl;
+ << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl
+ << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl;
delete obj;
root = 0;
}
diff --git a/src/quickwidgets/qquickwidget.h b/src/quickwidgets/qquickwidget.h
index a8bf03edfb..5bb6b49a49 100644
--- a/src/quickwidgets/qquickwidget.h
+++ b/src/quickwidgets/qquickwidget.h
@@ -56,7 +56,6 @@ class Q_QUICKWIDGETS_EXPORT QQuickWidget : public QWidget
Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
- Q_ENUMS(ResizeMode Status)
public:
explicit QQuickWidget(QWidget *parent = 0);
@@ -72,10 +71,12 @@ public:
QQuickItem *rootObject() const;
enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ Q_ENUM(ResizeMode)
ResizeMode resizeMode() const;
void setResizeMode(ResizeMode);
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
QList<QQmlError> errors() const;
diff --git a/sync.profile b/sync.profile
index f7255bea0a..28d0698da9 100644
--- a/sync.profile
+++ b/sync.profile
@@ -7,7 +7,7 @@
"QtQmlDevTools" => "$basedir/src/qmldevtools",
);
%moduleheaders = ( # restrict the module headers to those found in relative path
- "QtQmlDevTools" => "../qml/parser;../qml/jsruntime;../qml/qml/ftw;../qml/compiler;.",
+ "QtQmlDevTools" => "../qml/parser;../qml/jsruntime;../qml/qml/ftw;../qml/compiler;../qml/memory;.",
);
%deprecatedheaders = (
);
diff --git a/tests/auto/qml/animation/qsequentialanimationgroupjob/BLACKLIST b/tests/auto/qml/animation/qsequentialanimationgroupjob/BLACKLIST
new file mode 100644
index 0000000000..2afe6074d7
--- /dev/null
+++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/BLACKLIST
@@ -0,0 +1,2 @@
+[finishWithUncontrolledAnimation]
+*
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro
index fc1c0b537b..5a08418be1 100644
--- a/tests/auto/qml/debugger/debugger.pro
+++ b/tests/auto/qml/debugger/debugger.pro
@@ -12,6 +12,7 @@ PUBLICTESTS += \
PRIVATETESTS += \
qqmldebugclient \
+ qqmldebuglocal \
qqmldebugservice
SUBDIRS += $$PUBLICTESTS
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index 7ca69b6d44..99ba06ae31 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -76,9 +76,8 @@ void tst_QQmlDebugClient::initTestCase()
for (int i = 0; i < 50; ++i) {
// try for 5 seconds ...
m_conn->connectToHost("127.0.0.1", PORT);
- if (m_conn->waitForConnected())
+ if (m_conn->waitForConnected(100))
break;
- QTest::qSleep(100);
}
QVERIFY(m_conn->isConnected());
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/qqmldebuglocal.pro b/tests/auto/qml/debugger/qqmldebuglocal/qqmldebuglocal.pro
new file mode 100644
index 0000000000..b612da11de
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebuglocal/qqmldebuglocal.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qqmldebuglocal
+osx:CONFIG -= app_bundle
+
+HEADERS += ../shared/qqmldebugtestservice.h
+
+SOURCES += tst_qqmldebuglocal.cpp \
+ ../shared/qqmldebugtestservice.cpp
+
+INCLUDEPATH += ../shared
+include(../shared/debugutil.pri)
+
+CONFIG += parallel_test
+QT += qml-private testlib gui-private core-private
+
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 QT_QML_DEBUG_NO_WARNING
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
new file mode 100644
index 0000000000..b1219eabe4
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QSignalSpy>
+#include <QTimer>
+#include <QHostAddress>
+#include <QDebug>
+#include <QThread>
+#include <ctime>
+
+#include "debugutil_p.h"
+#include "qqmldebugtestservice.h"
+
+QString fileName;
+
+class tst_QQmlDebugLocal : public QObject
+{
+ Q_OBJECT
+
+private:
+ QQmlDebugConnection *m_conn;
+
+ bool connect();
+
+signals:
+ void waiting();
+ void parallel();
+
+private slots:
+ void initTestCase();
+
+ void name();
+ void state();
+ void sendMessage();
+};
+
+void tst_QQmlDebugLocal::initTestCase()
+{
+ const QString waitingMsg = QString("QML Debugger: Connecting to socket %1...").arg(fileName);
+ QTest::ignoreMessage(QtDebugMsg, waitingMsg.toLatin1().constData());
+
+ m_conn = new QQmlDebugConnection(this);
+ m_conn->startLocalServer(fileName);
+
+ new QQmlEngine(this);
+
+ QQmlDebugTestClient client("tst_QQmlDebugLocal::handshake()", m_conn);
+ QQmlDebugTestService service("tst_QQmlDebugLocal::handshake()");
+
+ for (int i = 0; i < 50; ++i) {
+ // try for 5 seconds ...
+ if (m_conn->waitForConnected(100))
+ break;
+ }
+
+ QVERIFY(m_conn->isConnected());
+
+ QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
+ QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
+}
+
+void tst_QQmlDebugLocal::name()
+{
+ QString name = "tst_QQmlDebugLocal::name()";
+
+ QQmlDebugClient client(name, m_conn);
+ QCOMPARE(client.name(), name);
+}
+
+void tst_QQmlDebugLocal::state()
+{
+ {
+ QQmlDebugConnection dummyConn;
+ QQmlDebugClient client("tst_QQmlDebugLocal::state()", &dummyConn);
+ QCOMPARE(client.state(), QQmlDebugClient::NotConnected);
+ QCOMPARE(client.serviceVersion(), -1.0f);
+ }
+
+ QQmlDebugTestClient client("tst_QQmlDebugLocal::state()", m_conn);
+ QCOMPARE(client.state(), QQmlDebugClient::Unavailable);
+
+ {
+ QQmlDebugTestService service("tst_QQmlDebugLocal::state()", 2);
+ QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
+ QCOMPARE(client.serviceVersion(), 2.0f);
+ }
+
+ QTRY_COMPARE(client.state(), QQmlDebugClient::Unavailable);
+
+ // duplicate plugin name
+ QTest::ignoreMessage(QtWarningMsg, "QQmlDebugClient: Conflicting plugin name \"tst_QQmlDebugLocal::state()\"");
+ QQmlDebugClient client2("tst_QQmlDebugLocal::state()", m_conn);
+ QCOMPARE(client2.state(), QQmlDebugClient::NotConnected);
+
+ QQmlDebugClient client3("tst_QQmlDebugLocal::state3()", 0);
+ QCOMPARE(client3.state(), QQmlDebugClient::NotConnected);
+}
+
+void tst_QQmlDebugLocal::sendMessage()
+{
+ QQmlDebugTestService service("tst_QQmlDebugLocal::sendMessage()");
+ QQmlDebugTestClient client("tst_QQmlDebugLocal::sendMessage()", m_conn);
+
+ QByteArray msg = "hello!";
+
+ QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
+
+ client.sendMessage(msg);
+ QByteArray resp = client.waitForResponse();
+ QCOMPARE(resp, msg);
+}
+
+int main(int argc, char *argv[])
+{
+ fileName = QString::fromLatin1("tst_QQmlDebugLocal%1").arg(time(0));
+
+ int _argc = argc + 1;
+ char **_argv = new char*[_argc];
+ for (int i = 0; i < argc; ++i)
+ _argv[i] = argv[i];
+ char *arg = strdup((QString::fromLatin1("-qmljsdebugger=file:") + fileName).toLatin1().data());
+ _argv[_argc - 1] = arg;
+
+ QGuiApplication app(_argc, _argv);
+ tst_QQmlDebugLocal tc;
+ return QTest::qExec(&tc, _argc, _argv);
+ delete _argv;
+}
+
+#include "tst_qqmldebuglocal.moc"
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.pro b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.pro
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.pro
diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
index de05594161..bb8b8f0823 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -130,7 +130,7 @@ void tst_QQmlDebugService::name()
{
QString name = "tst_QQmlDebugService::name()";
- QQmlDebugService service(name, 1);
+ QQmlDebugTestService service(name, 1);
QCOMPARE(service.name(), name);
}
@@ -138,7 +138,7 @@ void tst_QQmlDebugService::version()
{
QString name = "tst_QQmlDebugService::name()";
- QQmlDebugService service(name, 2);
+ QQmlDebugTestService service(name, 2);
QCOMPARE(service.version(), 2.0f);
}
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index d3bb5c38ca..5090580cc5 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -87,6 +87,8 @@ public:
class tst_QQmlEngineDebugService : public QObject
{
Q_OBJECT
+public:
+ tst_QQmlEngineDebugService() : m_conn(0), m_dbg(0), m_engine(0), m_rootItem(0) {}
private:
QmlDebugObjectReference findRootObject(int context = 0,
@@ -1018,7 +1020,7 @@ void tst_QQmlEngineDebugService::setBindingForObject()
mouseAreaObject = m_dbg->object();
onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered");
QCOMPARE(onEnteredRef.name, QString("onEntered"));
- QCOMPARE(onEnteredRef.value, QVariant("{console.log('hello, world') }"));
+ QCOMPARE(onEnteredRef.value, QVariant("function() { [code] }"));
}
void tst_QQmlEngineDebugService::resetBindingForObject()
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
index 5ed866c04d..23741f2a22 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
@@ -112,12 +112,14 @@ void tst_QQmlInspector::cleanup()
void tst_QQmlInspector::connect()
{
startQmlsceneProcess("qtquick2.qml");
+ QVERIFY(m_client);
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
}
void tst_QQmlInspector::showAppOnTop()
{
startQmlsceneProcess("qtquick2.qml");
+ QVERIFY(m_client);
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setShowAppOnTop(true);
@@ -132,6 +134,7 @@ void tst_QQmlInspector::showAppOnTop()
void tst_QQmlInspector::reloadQml()
{
startQmlsceneProcess("qtquick2.qml");
+ QVERIFY(m_client);
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
QByteArray fileContents;
@@ -157,6 +160,7 @@ void tst_QQmlInspector::reloadQml()
void tst_QQmlInspector::reloadQmlWindow()
{
startQmlsceneProcess("window.qml");
+ QVERIFY(m_client);
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
QByteArray fileContents;
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 094bf43549..8a83c25c19 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -509,7 +509,7 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
void tst_QQmlProfilerService::cleanup()
{
- if (QTest::currentTestFailed()) {
+ if (m_client && QTest::currentTestFailed()) {
qDebug() << "QML Messages:" << m_client->qmlMessages.count();
int i = 0;
foreach (const QQmlProfilerData &data, m_client->qmlMessages) {
@@ -547,7 +547,7 @@ void tst_QQmlProfilerService::cleanup()
qDebug() << "Process State:" << (m_process ? m_process->state() : QLatin1String("null"));
qDebug() << "Application Output:" << (m_process ? m_process->output() : QLatin1String("null"));
qDebug() << "Connection State:" << (m_connection ? m_connection->stateString() : QLatin1String("null"));
- qDebug() << "Client State:" << (m_client ? m_client->stateString() : QLatin1String("null"));
+ qDebug() << "Client State:" << m_client->stateString();
}
delete m_process;
m_process = 0;
diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
index c7281dec69..0f7e572e02 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
@@ -39,6 +39,8 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qtimer.h>
#include <QtNetwork/qnetworkproxy.h>
+#include <QtNetwork/qlocalserver.h>
+#include <QtNetwork/qlocalsocket.h>
const int protocolVersion = 1;
const QString serverId = QLatin1String("QDeclarativeDebugServer");
@@ -61,6 +63,7 @@ public:
QQmlDebugConnection *q;
QPacketProtocol *protocol;
QIODevice *device;
+ QLocalServer *server;
QEventLoop handshakeEventLoop;
QTimer handshakeTimer;
@@ -72,6 +75,10 @@ public:
void connectDeviceSignals();
public Q_SLOTS:
+ void forwardStateChange(QLocalSocket::LocalSocketState state);
+ void forwardError(QLocalSocket::LocalSocketError error);
+
+ void newConnection();
void connected();
void readyRead();
void deviceAboutToClose();
@@ -79,7 +86,7 @@ public Q_SLOTS:
};
QQmlDebugConnectionPrivate::QQmlDebugConnectionPrivate(QQmlDebugConnection *c)
- : QObject(c), q(c), protocol(0), device(0), gotHello(false)
+ : QObject(c), q(c), protocol(0), device(0), server(0), gotHello(false)
{
protocol = new QPacketProtocol(q, this);
QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
@@ -307,10 +314,13 @@ void QQmlDebugConnection::close()
bool QQmlDebugConnection::waitForConnected(int msecs)
{
QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
- if (!socket)
- return false;
- if (!socket->waitForConnected(msecs))
+ if (!socket) {
+ if (!d->server || (!d->server->hasPendingConnections() &&
+ !d->server->waitForNewConnection(msecs)))
+ return false;
+ } else if (!socket->waitForConnected(msecs)) {
return false;
+ }
// wait for handshake
d->handshakeTimer.start();
d->handshakeEventLoop.exec();
@@ -336,9 +346,13 @@ QString QQmlDebugConnection::stateString() const
QAbstractSocket::SocketState QQmlDebugConnection::state() const
{
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
- if (socket)
- return socket->state();
+ QAbstractSocket *abstractSocket = qobject_cast<QAbstractSocket*>(d->device);
+ if (abstractSocket)
+ return abstractSocket->state();
+
+ QLocalSocket *localSocket = qobject_cast<QLocalSocket*>(d->device);
+ if (localSocket)
+ return static_cast<QAbstractSocket::SocketState>(localSocket->state());
return QAbstractSocket::UnconnectedState;
}
@@ -366,6 +380,29 @@ void QQmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
QIODevice::open(ReadWrite | Unbuffered);
}
+void QQmlDebugConnection::startLocalServer(const QString &fileName)
+{
+ d->gotHello = false;
+ d->server = new QLocalServer(d);
+ // QueuedConnection so that waitForNewConnection() returns true.
+ connect(d->server, SIGNAL(newConnection()), d, SLOT(newConnection()), Qt::QueuedConnection);
+ d->server->listen(fileName);
+ QIODevice::open(ReadWrite | Unbuffered);
+}
+
+void QQmlDebugConnectionPrivate::newConnection()
+{
+ QLocalSocket *socket = server->nextPendingConnection();
+ server->close();
+ device = socket;
+ connectDeviceSignals();
+ connect(socket, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)),
+ this, SLOT(forwardStateChange(QLocalSocket::LocalSocketState)));
+ connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
+ this, SLOT(forwardError(QLocalSocket::LocalSocketError)));
+ emit q->connected();
+}
+
void QQmlDebugConnectionPrivate::connectDeviceSignals()
{
connect(device, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)));
@@ -373,7 +410,15 @@ void QQmlDebugConnectionPrivate::connectDeviceSignals()
connect(device, SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose()));
}
-//
+void QQmlDebugConnectionPrivate::forwardStateChange(QLocalSocket::LocalSocketState state)
+{
+ emit q->stateChanged(static_cast<QAbstractSocket::SocketState>(state));
+}
+
+void QQmlDebugConnectionPrivate::forwardError(QLocalSocket::LocalSocketError error)
+{
+ emit q->error(static_cast<QAbstractSocket::SocketError>(error));
+}
QQmlDebugClientPrivate::QQmlDebugClientPrivate()
: connection(0)
diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.h b/tests/auto/qml/debugger/shared/qqmldebugclient.h
index 52f428cca7..fe9da693c8 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugclient.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugclient.h
@@ -46,6 +46,7 @@ public:
~QQmlDebugConnection();
void connectToHost(const QString &hostName, quint16 port);
+ void startLocalServer(const QString &fileName);
void setDataStreamVersion(int dataStreamVersion);
int dataStreamVersion();
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index a5c3211f0d..6f1bea6d92 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -36,6 +36,7 @@ PRIVATETESTS += \
qqmldirparser \
qqmlglobal \
qqmllanguage \
+ qqmlopenmetaobject \
qqmlproperty \
qqmlpropertycache \
qqmlpropertymap \
@@ -59,7 +60,8 @@ PRIVATETESTS += \
qqmlenginecleanup \
v4misc \
qqmltranslation \
- qqmlimport
+ qqmlimport \
+ qqmlobjectmodel
qtHaveModule(widgets) {
PUBLICTESTS += \
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index bb159d5931..4c1f827915 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -110,6 +110,7 @@ private slots:
void qmlCreateParentReference();
void async();
void asyncHierarchy();
+ void asyncForceSync();
void componentUrlCanonicalization();
void onDestructionLookup();
void onDestructionCount();
@@ -371,6 +372,35 @@ void tst_qqmlcomponent::asyncHierarchy()
delete root;
}
+void tst_qqmlcomponent::asyncForceSync()
+{
+ {
+ // 1) make sure that HTTP URLs cannot be completed synchronously
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
+
+ // ensure that the item hierarchy is compiled correctly.
+ QQmlComponent component(&engine);
+ component.loadUrl(server.url("/TestComponent.2.qml"), QQmlComponent::Asynchronous);
+ QCOMPARE(component.status(), QQmlComponent::Loading);
+ QQmlComponent component2(&engine, server.url("/TestComponent.2.qml"), QQmlComponent::PreferSynchronous);
+ QCOMPARE(component2.status(), QQmlComponent::Loading);
+ }
+ {
+ // 2) make sure that file:// URL can be completed synchronously
+
+ // ensure that the item hierarchy is compiled correctly.
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("/TestComponent.2.qml"), QQmlComponent::Asynchronous);
+ QCOMPARE(component.status(), QQmlComponent::Loading);
+ QQmlComponent component2(&engine, testFileUrl("/TestComponent.2.qml"), QQmlComponent::PreferSynchronous);
+ QCOMPARE(component2.status(), QQmlComponent::Ready);
+ QCOMPARE(component.status(), QQmlComponent::Loading);
+ QTRY_COMPARE_WITH_TIMEOUT(component.status(), QQmlComponent::Ready, 0);
+ }
+}
+
void tst_qqmlcomponent::componentUrlCanonicalization()
{
// ensure that url canonicalization succeeds so that type information
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index bbccf7b94b..eb4a3147d3 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -1253,7 +1253,7 @@ public:
Q_INVOKABLE void addReference(QObject *other)
{
QQmlData *ddata = QQmlData::get(this);
- assert(ddata);
+ Q_ASSERT(ddata);
QV4::ExecutionEngine *v4 = ddata->jsWrapper.engine();
Q_ASSERT(v4);
QV4::Scope scope(v4);
diff --git a/tests/auto/qml/qqmlobjectmodel/qqmlobjectmodel.pro b/tests/auto/qml/qqmlobjectmodel/qqmlobjectmodel.pro
new file mode 100644
index 0000000000..f8232f8854
--- /dev/null
+++ b/tests/auto/qml/qqmlobjectmodel/qqmlobjectmodel.pro
@@ -0,0 +1,10 @@
+CONFIG += testcase
+TARGET = tst_qqmlobjectmodel
+osx:CONFIG -= app_bundle
+
+SOURCES += tst_qqmlobjectmodel.cpp
+
+CONFIG += parallel_test
+
+QT += qml testlib
+QT += core-private qml-private
diff --git a/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp b/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
new file mode 100644
index 0000000000..001739e38d
--- /dev/null
+++ b/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtTest/qsignalspy.h>
+#include <QtTest/qtest.h>
+
+class tst_QQmlObjectModel : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void changes();
+};
+
+static bool compareItems(QQmlObjectModel *model, const QObjectList &items)
+{
+ for (int i = 0; i < items.count(); ++i) {
+ if (model->get(i) != items.at(i))
+ return false;
+ }
+ return true;
+}
+
+void tst_QQmlObjectModel::changes()
+{
+ QQmlObjectModel model;
+
+ QSignalSpy countSpy(&model, SIGNAL(countChanged()));
+ QSignalSpy childrenSpy(&model, SIGNAL(childrenChanged()));
+
+ int count = 0;
+ int countSignals = 0;
+ int childrenSignals = 0;
+
+ QObjectList items;
+ QObject item0, item1, item2, item3;
+
+ // append(item0) -> [item0]
+ model.append(&item0); items.append(&item0);
+ QCOMPARE(model.count(), ++count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), ++countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // insert(0, item1) -> [item1, item0]
+ model.insert(0, &item1); items.insert(0, &item1);
+ QCOMPARE(model.count(), ++count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), ++countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // append(item2) -> [item1, item0, item2]
+ model.append(&item2); items.append(&item2);
+ QCOMPARE(model.count(), ++count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), ++countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // insert(2, item3) -> [item1, item0, item3, item2]
+ model.insert(2, &item3); items.insert(2, &item3);
+ QCOMPARE(model.count(), ++count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), ++countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // move(0, 1) -> [item0, item1, item3, item2]
+ model.move(0, 1); items.move(0, 1);
+ QCOMPARE(model.count(), count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // move(3, 2) -> [item0, item1, item2, item3]
+ model.move(3, 2); items.move(3, 2);
+ QCOMPARE(model.count(), count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // remove(0) -> [item1, item2, item3]
+ model.remove(0); items.removeAt(0);
+ QCOMPARE(model.count(), --count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), ++countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // remove(2) -> [item1, item2]
+ model.remove(2); items.removeAt(2);
+ QCOMPARE(model.count(), --count);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), ++countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+
+ // clear() -> []
+ model.clear(); items.clear();
+ QCOMPARE(model.count(), 0);
+ QVERIFY(compareItems(&model, items));
+ QCOMPARE(countSpy.count(), ++countSignals);
+ QCOMPARE(childrenSpy.count(), ++childrenSignals);
+}
+
+QTEST_MAIN(tst_QQmlObjectModel)
+
+#include "tst_qqmlobjectmodel.moc"
diff --git a/tests/auto/qml/qqmlopenmetaobject/qqmlopenmetaobject.pro b/tests/auto/qml/qqmlopenmetaobject/qqmlopenmetaobject.pro
new file mode 100644
index 0000000000..c81394e77e
--- /dev/null
+++ b/tests/auto/qml/qqmlopenmetaobject/qqmlopenmetaobject.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qqmlopenmetaobject
+osx:CONFIG -= app_bundle
+
+SOURCES += tst_qqmlopenmetaobject.cpp
+
+CONFIG += parallel_test
+QT += core-private gui-private qml-private testlib
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/src/qml/jsruntime/qv4qmlextensions_p.h b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
index e4b9f75298..429f45b875 100644
--- a/src/qml/jsruntime/qv4qmlextensions_p.h
+++ b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -30,29 +30,40 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QV4QMLEXTENSIONS_P_H
-#define QV4QMLEXTENSIONS_P_H
-#include <qtqmlglobal.h>
-#include <qv4global_p.h>
+#include <qtest.h>
+#include <private/qqmlopenmetaobject_p.h>
+#include <QtQml/qqmlengine.h>
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-struct Q_QML_EXPORT QmlExtensions
+class tst_qqmlopenmetaobject : public QObject
{
- QmlExtensions()
- : valueTypeWrapperPrototype(0)
- {}
+ Q_OBJECT
+public:
+ tst_qqmlopenmetaobject() {}
- Heap::Object *valueTypeWrapperPrototype;
+private slots:
+ void createProperties();
+};
- void markObjects(ExecutionEngine *e);
+class CustomObject: public QObject
+{
+ Q_OBJECT
+public:
+ CustomObject(QObject *parent = 0)
+ : QObject(parent) {}
};
-} // namespace QV4
+void tst_qqmlopenmetaobject::createProperties()
+{
+ QQmlEngine engine;
+ CustomObject object;
+ const QQmlRefPointer<QQmlOpenMetaObjectType> mot = new QQmlOpenMetaObjectType(object.metaObject(), &engine);
+ QQmlOpenMetaObject *const mo = new QQmlOpenMetaObject(&object, mot);
+ mo->setCached(true);
+ mot->createProperty("customProperty");
+ QVERIFY(true);
+}
-QT_END_NAMESPACE
+QTEST_MAIN(tst_qqmlopenmetaobject)
-#endif
+#include "tst_qqmlopenmetaobject.moc"
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index c4b2325843..c228adafd4 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -158,10 +158,10 @@ void tst_qqmlproperty::qmlmetaproperty()
QObject *obj = new QObject;
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
- QVERIFY(binding != 0);
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(obj, QObjectPrivate::get(obj)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QCOMPARE(prop.name(), QString());
@@ -189,10 +189,10 @@ void tst_qqmlproperty::qmlmetaproperty()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QVERIFY(prop.property().name() == 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -407,10 +407,10 @@ void tst_qqmlproperty::qmlmetaproperty_object()
{
QQmlProperty prop(&object);
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
- QVERIFY(binding != 0);
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -440,10 +440,10 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QVERIFY(prop.property().name() == 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -454,11 +454,11 @@ void tst_qqmlproperty::qmlmetaproperty_object()
{
QQmlProperty prop(&dobject);
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -489,11 +489,11 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -510,10 +510,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&object, QString("defaultProperty"));
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
- QVERIFY(binding != 0);
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -543,10 +543,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QVERIFY(prop.property().name() == 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -557,11 +557,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&dobject, QString("defaultProperty"));
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -592,11 +592,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -607,11 +607,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&dobject, QString("onClicked"));
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -641,10 +641,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QCOMPARE(prop.property().name(), (const char *)0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
@@ -656,11 +656,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -690,10 +690,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QCOMPARE(prop.property().name(), (const char *)0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
@@ -711,10 +711,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
{
QQmlProperty prop(&object, engine.rootContext());
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
- QVERIFY(binding != 0);
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -744,10 +744,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QVERIFY(prop.property().name() == 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -758,11 +758,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
{
QQmlProperty prop(&dobject, engine.rootContext());
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -793,11 +793,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -814,10 +814,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&object, QString("defaultProperty"), engine.rootContext());
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
- QVERIFY(binding != 0);
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -847,10 +847,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QVERIFY(prop.property().name() == 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -861,11 +861,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -896,11 +896,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -911,11 +911,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&dobject, QString("onClicked"), engine.rootContext());
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -945,10 +945,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QCOMPARE(prop.property().name(), (const char *)0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
@@ -960,11 +960,11 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
- QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
+ QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
- QVERIFY(binding != 0);
+ QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
- QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -994,10 +994,10 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(prop.propertyTypeName(), (const char *)0);
QCOMPARE(prop.property().name(), (const char *)0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
@@ -1145,7 +1145,7 @@ void tst_qqmlproperty::read()
QQmlProperty p(&o, "onClicked");
QCOMPARE(p.read(), QVariant());
- QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1)));
+ QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.read(), QVariant());
@@ -1157,7 +1157,7 @@ void tst_qqmlproperty::read()
QQmlProperty p(&o, "onPropertyWithNotifyChanged");
QCOMPARE(p.read(), QVariant());
- QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1)));
+ QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.read(), QVariant());
@@ -1336,7 +1336,7 @@ void tst_qqmlproperty::write()
QQmlProperty p(&o, "onClicked");
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
- QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1)));
+ QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
@@ -1350,7 +1350,7 @@ void tst_qqmlproperty::write()
QQmlProperty p(&o, "onPropertyWithNotifyChanged");
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
- QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1)));
+ QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/cdata.qml b/tests/auto/qml/qqmlxmlhttprequest/data/cdata.qml
index f558fdadc6..e1b690dbf3 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/cdata.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/cdata.qml
@@ -3,6 +3,7 @@ import QtQuick 2.0
QtObject {
property bool xmlTest: false
property bool dataOK: false
+ property int status: 0
function checkCData(text, whitespacetext)
{
@@ -114,12 +115,11 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
if (x.readyState == XMLHttpRequest.DONE) {
-
dataOK = true;
+ status = x.status;
if (x.responseXML != null)
checkXML(x.responseXML);
-
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/json.data b/tests/auto/qml/qqmlxmlhttprequest/data/json.data
new file mode 100644
index 0000000000..7925375293
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/json.data
@@ -0,0 +1,6 @@
+{"widget": {
+ "debug": "on",
+ "window": {
+ "name": "main_window",
+ "width": 500
+}}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
index 234d759284..b9f0ab6e66 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
@@ -3,6 +3,7 @@ import QtQuick 2.0
QtObject {
property string url
property int readSize: 0
+ property int status: 0
Component.onCompleted: {
@@ -12,6 +13,7 @@ QtObject {
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE) {
+ status = request.status;
var arrayBuffer = request.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml
new file mode 100644
index 0000000000..3fc116e675
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+
+QtObject {
+ property string url;
+ property bool result: false
+ property string correctjsondata : "{\"widget\":{\"debug\":\"on\",\"window\":{\"name\":\"main_window\",\"width\":500}}}"
+
+ Component.onCompleted: {
+ var request = new XMLHttpRequest();
+ request.open("GET", url, true);
+ request.responseType = "json";
+
+ request.onreadystatechange = function() {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ var jsonData = JSON.stringify(request.response);
+ result = (correctjsondata == jsonData);
+ }
+ }
+
+ request.send(null);
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
new file mode 100644
index 0000000000..97b016f50a
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
@@ -0,0 +1,7 @@
+GET /json.data HTTP/1.1
+Accept-Language: en-US,*
+Content-Type: application/jsonrequest
+Connection: Keep-Alive
+Accept-Encoding: gzip, deflate
+User-Agent: Mozilla/5.0
+Host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply
new file mode 100644
index 0000000000..f1ee73d623
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Connection: close
+Content-Type: application/jsonrequest
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/text.qml b/tests/auto/qml/qqmlxmlhttprequest/data/text.qml
index b79e0bc7b1..972557358b 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/text.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/text.qml
@@ -3,6 +3,7 @@ import QtQuick 2.0
QtObject {
property bool xmlTest: false
property bool dataOK: false
+ property int status: 0
function checkText(text, whitespacetext)
{
@@ -111,12 +112,11 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
if (x.readyState == XMLHttpRequest.DONE) {
-
dataOK = true;
+ status = x.status;
if (x.responseXML != null)
checkXML(x.responseXML);
-
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index c159dc8420..56314a29f5 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -88,6 +88,7 @@ private slots:
void getAllResponseHeaders_sent();
void getAllResponseHeaders_args();
void getBinaryData();
+ void getJsonData();
void status();
void status_data();
void statusText();
@@ -846,6 +847,24 @@ void tst_qqmlxmlhttprequest::getBinaryData()
QFileInfo fileInfo("data/qml_logo.png");
QTRY_VERIFY(object->property("readSize").toInt() == fileInfo.size());
+ QCOMPARE(object->property("status").toInt(), 200);
+}
+
+void tst_qqmlxmlhttprequest::getJsonData()
+{
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("receive_json_data.expect"),
+ testFileUrl("receive_binary_data.reply"),
+ testFileUrl("json.data")));
+
+ QQmlComponent component(&engine, testFileUrl("receiveJsonData.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/json.data"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("result").toBool());
}
void tst_qqmlxmlhttprequest::status()
@@ -1146,6 +1165,7 @@ void tst_qqmlxmlhttprequest::text()
QTRY_VERIFY(object->property("dataOK").toBool() == true);
QCOMPARE(object->property("xmlTest").toBool(), true);
+ QCOMPARE(object->property("status").toInt(), 200);
}
// Test the CDataSection DOM element
@@ -1158,6 +1178,7 @@ void tst_qqmlxmlhttprequest::cdata()
QTRY_VERIFY(object->property("dataOK").toBool() == true);
QCOMPARE(object->property("xmlTest").toBool(), true);
+ QCOMPARE(object->property("status").toInt(), 200);
}
void tst_qqmlxmlhttprequest::stateChangeCallingContext()
diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
index 056b24d167..ee0f55813d 100644
--- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
@@ -85,7 +85,7 @@ public:
QV4::ScopedString name(scope, v4->newString(functionName));
QV4::ScopedContext ctx(scope, v4->rootContext());
QV4::ScopedValue function(scope, BuiltinFunction::create(ctx, name, injectedFunction));
- v4->globalObject()->put(name, function);
+ v4->globalObject->put(name, function);
}
signals:
@@ -131,7 +131,7 @@ protected:
virtual void addObject(const QString &name, const QV4::Value &value)
{
QV4::Scope scope(engine());
- QV4::ScopedObject obj(scope, value.asObject());
+ QV4::ScopedObject obj(scope, value.as<Object>());
QVariantMap props, *prev = &props;
qSwap(destination, prev);
diff --git a/tests/auto/qmldevtools/compile/tst_compile.cpp b/tests/auto/qmldevtools/compile/tst_compile.cpp
index b19260779c..4637f14739 100644
--- a/tests/auto/qmldevtools/compile/tst_compile.cpp
+++ b/tests/auto/qmldevtools/compile/tst_compile.cpp
@@ -37,7 +37,6 @@
#include <private/qqmljsastvisitor_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmlirbuilder_p.h>
-#include <private/qv4value_inl_p.h>
#include <private/qv4codegen_p.h>
int main()
diff --git a/tests/auto/qmltest/BLACKLIST b/tests/auto/qmltest/BLACKLIST
new file mode 100644
index 0000000000..cd8b1181e0
--- /dev/null
+++ b/tests/auto/qmltest/BLACKLIST
@@ -0,0 +1,5 @@
+# Blacklist for testing
+[SelfTests::test_blacklisted_fail]
+*
+[SelfTests::test_blacklistWithData:test2]
+*
diff --git a/tests/auto/qmltest/objectmodel/tst_objectmodel.qml b/tests/auto/qmltest/objectmodel/tst_objectmodel.qml
new file mode 100644
index 0000000000..e8205a1486
--- /dev/null
+++ b/tests/auto/qmltest/objectmodel/tst_objectmodel.qml
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 QtQml 2.1
+import QtQml.Models 2.3
+import QtTest 1.1
+
+TestCase {
+ name: "ObjectModel"
+
+ ObjectModel {
+ id: model
+ QtObject { id: static0 }
+ QtObject { id: static1 }
+ QtObject { id: static2 }
+ }
+
+ Component { id: object; QtObject { } }
+
+ function test_attached_index() {
+ compare(model.count, 3)
+ compare(static0.ObjectModel.index, 0)
+ compare(static1.ObjectModel.index, 1)
+ compare(static2.ObjectModel.index, 2)
+
+ var dynamic0 = object.createObject(model, {objectName: "dynamic0"})
+ compare(dynamic0.ObjectModel.index, -1)
+ model.append(dynamic0) // -> [static0, static1, static2, dynamic0]
+ compare(model.count, 4)
+ for (var i = 0; i < model.count; ++i)
+ compare(model.get(i).ObjectModel.index, i)
+
+ var dynamic1 = object.createObject(model, {objectName: "dynamic1"})
+ compare(dynamic1.ObjectModel.index, -1)
+ model.insert(0, dynamic1) // -> [dynamic1, static0, static1, static2, dynamic0]
+ compare(model.count, 5)
+ for (i = 0; i < model.count; ++i)
+ compare(model.get(i).ObjectModel.index, i)
+
+ model.move(1, 3) // -> [dynamic1, static1, static2, static0, dynamic0]
+ compare(model.count, 5)
+ for (i = 0; i < model.count; ++i)
+ compare(model.get(i).ObjectModel.index, i)
+
+ model.move(4, 0) // -> [dynamic0, dynamic1, static1, static2, static0]
+ compare(model.count, 5)
+ for (i = 0; i < model.count; ++i)
+ compare(model.get(i).ObjectModel.index, i)
+
+ model.remove(1) // -> [dynamic0, static1, static2, static0]
+ compare(model.count, 4)
+ compare(dynamic1.ObjectModel.index, -1)
+ for (i = 0; i < model.count; ++i)
+ compare(model.get(i).ObjectModel.index, i)
+
+ model.clear()
+ compare(static0.ObjectModel.index, -1)
+ compare(static1.ObjectModel.index, -1)
+ compare(static2.ObjectModel.index, -1)
+ compare(dynamic0.ObjectModel.index, -1)
+ compare(dynamic1.ObjectModel.index, -1)
+ }
+}
diff --git a/tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml b/tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml
new file mode 100644
index 0000000000..9de9a621f6
--- /dev/null
+++ b/tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.2
+import QtQml.Models 2.3
+import QtTest 1.1
+
+Item {
+ id: top
+
+ ListView {
+ id: listViewWithObjectModel // QTBUG-46798
+ anchors.fill: parent
+ model: ObjectModel {
+ id: objectModel
+ Rectangle { width: 160; height: 160; color: "red" }
+ Rectangle { width: 160; height: 160; color: "green" }
+ Rectangle { width: 160; height: 160; color: "blue" }
+ }
+ }
+
+ TestCase {
+ name: "QTBUG-46798"
+ when: windowShown
+
+ function test_bug46798() {
+ var item = objectModel.get(0)
+ if (item) {
+ objectModel.remove(0)
+ item.destroy()
+ }
+ }
+ }
+}
diff --git a/src/qml/jsruntime/qv4qmlextensions.cpp b/tests/auto/qmltest/selftests/tst_grabImage.qml
index c1c4e0ec78..7a758ae8fc 100644
--- a/src/qml/jsruntime/qv4qmlextensions.cpp
+++ b/tests/auto/qmltest/selftests/tst_grabImage.qml
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,13 +31,28 @@
**
****************************************************************************/
-#include "qv4qmlextensions_p.h"
-#include "qv4object_p.h"
+import QtQuick 2.0
+import QtTest 1.1
-using namespace QV4;
+TestCase {
+ id: testCase
+ name: "tst_grabImage"
+ when: windowShown
-void QmlExtensions::markObjects(ExecutionEngine *e)
-{
- if (valueTypeWrapperPrototype)
- valueTypeWrapperPrototype->mark(e);
+ function test_equals() {
+ var rect = Qt.createQmlObject("import QtQuick 2.0; Rectangle { color: 'red'; width: 10; height: 10; }", testCase);
+ verify(rect);
+ var oldImage = grabImage(rect);
+ rect.width += 10;
+ var newImage = grabImage(rect);
+ verify(!newImage.equals(oldImage));
+
+ oldImage = grabImage(rect);
+ // Don't change anything...
+ newImage = grabImage(rect);
+ verify(newImage.equals(oldImage));
+
+ verify(!newImage.equals(null));
+ verify(!newImage.equals(undefined));
+ }
}
diff --git a/tests/auto/qmltest/selftests/tst_selftests.qml b/tests/auto/qmltest/selftests/tst_selftests.qml
index 0d09f9536a..a372107e26 100644
--- a/tests/auto/qmltest/selftests/tst_selftests.qml
+++ b/tests/auto/qmltest/selftests/tst_selftests.qml
@@ -278,4 +278,30 @@ TestCase {
}
verify(caught)
}
+
+ function test_blacklisted_fail()
+ {
+ verify(false)
+ }
+
+ function test_blacklistWithData_data() {
+ return [
+ {
+ tag: "test1",
+ success: true
+ },
+ {
+ tag: "test2",
+ success: false
+ },
+ {
+ tag: "test3",
+ success: true
+ }
+ ]
+ }
+
+ function test_blacklistWithData(row) {
+ verify(row.success)
+ }
}
diff --git a/tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml b/tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml
new file mode 100644
index 0000000000..c9eadde373
--- /dev/null
+++ b/tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.6
+import QtTest 1.1
+
+Row {
+ width: 100
+ height: 50
+ spacing: 10
+
+ property alias control1: _control1
+ property alias control2: _control2
+ TextEdit {
+ id: _control1
+ text: 'A'
+ property bool myeditingfinished: false
+ onEditingFinished: myeditingfinished = true
+ activeFocusOnTab: true
+ }
+ TextEdit {
+ id: _control2
+ text: 'B'
+ property bool myeditingfinished: false
+ onEditingFinished: myeditingfinished = true
+ activeFocusOnTab: true
+ }
+
+ TestCase {
+ name: "TextEdit_editingFinished"
+ when: windowShown
+
+ function test_editingFinished() {
+ control1.forceActiveFocus()
+ verify(control1.activeFocus)
+ verify(!control2.activeFocus)
+
+ verify(control1.myeditingfinished === false)
+ verify(control2.myeditingfinished === false)
+
+ keyClick(Qt.Key_Backtab)
+ verify(!control1.activeFocus)
+ verify(control2.activeFocus)
+ verify(control1.myeditingfinished === true)
+
+ keyClick(Qt.Key_Backtab)
+ verify(control1.activeFocus)
+ verify(!control2.activeFocus)
+ verify(control2.myeditingfinished === true)
+ }
+ }
+}
diff --git a/tests/auto/quick/nokeywords/tst_nokeywords.cpp b/tests/auto/quick/nokeywords/tst_nokeywords.cpp
index 378af7ea90..58746447f0 100644
--- a/tests/auto/quick/nokeywords/tst_nokeywords.cpp
+++ b/tests/auto/quick/nokeywords/tst_nokeywords.cpp
@@ -67,7 +67,6 @@
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgrenderloop_p.h>
#include <QtQuick/private/qsgrendernode_p.h>
-#include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h>
#include <QtQuick/private/qsgtexturematerial_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <QtQuick/private/qsgthreadedrenderloop_p.h>
diff --git a/tests/auto/quick/qquickbehaviors/BLACKLIST b/tests/auto/quick/qquickbehaviors/BLACKLIST
new file mode 100644
index 0000000000..9be4da176d
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/BLACKLIST
@@ -0,0 +1,2 @@
+[currentValue]
+windows
diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
index b96f1de930..643bed4376 100644
--- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
+++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
@@ -82,39 +82,35 @@ void tst_qquickbehaviors::simpleBehavior()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("simple.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QTRY_VERIFY(qobject_cast<QQuickBehavior*>(rect->findChild<QQuickBehavior*>("MyBehavior"))->animation());
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
//i.e. the behavior has been triggered
-
- delete rect;
}
void tst_qquickbehaviors::scriptTriggered()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("scripttrigger.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
rect->setColor(QColor("red"));
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
//i.e. the behavior has been triggered
-
- delete rect;
}
void tst_qquickbehaviors::cppTriggered()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("cpptrigger.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
QTRY_VERIFY(innerRect);
@@ -122,60 +118,52 @@ void tst_qquickbehaviors::cppTriggered()
innerRect->setProperty("x", 200);
QTRY_VERIFY(innerRect->x() > 0);
QTRY_VERIFY(innerRect->x() < 200); //i.e. the behavior has been triggered
-
- delete rect;
}
void tst_qquickbehaviors::loop()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("loop.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
//don't crash
- QQuickItemPrivate::get(rect)->setState("moved");
-
- delete rect;
+ QQuickItemPrivate::get(rect.data())->setState("moved");
}
void tst_qquickbehaviors::colorBehavior()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("color.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("red");
+ QQuickItemPrivate::get(rect.data())->setState("red");
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->color() != QColor("red"));
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->color() != QColor("green"));
//i.e. the behavior has been triggered
-
- delete rect;
}
void tst_qquickbehaviors::parentBehavior()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("parent.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("reparented");
+ QQuickItemPrivate::get(rect.data())->setState("reparented");
QTRY_VERIFY(rect->findChild<QQuickRectangle*>("MyRect")->parentItem() != rect->findChild<QQuickItem*>("NewParent"));
QTRY_VERIFY(rect->findChild<QQuickRectangle*>("MyRect")->parentItem() == rect->findChild<QQuickItem*>("NewParent"));
-
- delete rect;
}
void tst_qquickbehaviors::replaceBinding()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("binding.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
QTRY_VERIFY(innerRect);
QTRY_VERIFY(innerRect->x() > 0);
@@ -187,7 +175,7 @@ void tst_qquickbehaviors::replaceBinding()
rect->setProperty("movedx", 210);
QTRY_COMPARE(innerRect->x(), (qreal)210);
- QQuickItemPrivate::get(rect)->setState("");
+ QQuickItemPrivate::get(rect.data())->setState("");
QTRY_VERIFY(innerRect->x() > 10);
QTRY_VERIFY(innerRect->x() < 210); //i.e. the behavior has been triggered
QTRY_COMPARE(innerRect->x(), (qreal)10);
@@ -195,8 +183,6 @@ void tst_qquickbehaviors::replaceBinding()
QTRY_COMPARE(innerRect->x(), (qreal)10);
rect->setProperty("basex", 20);
QTRY_COMPARE(innerRect->x(), (qreal)20);
-
- delete rect;
}
void tst_qquickbehaviors::group()
@@ -205,32 +191,27 @@ void tst_qquickbehaviors::group()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("groupProperty.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- qDebug() << c.errorString();
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
//QTest::qWait(200);
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
//i.e. the behavior has been triggered
-
- delete rect;
}
*/
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("groupProperty2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->border()->width() > 0);
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->border()->width() < 4);
//i.e. the behavior has been triggered
-
- delete rect;
}
}
@@ -238,56 +219,48 @@ void tst_qquickbehaviors::valueType()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("valueType.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
//QTBUG-20827
QCOMPARE(rect->color(), QColor::fromRgb(255,0,255));
-
- delete rect;
}
void tst_qquickbehaviors::emptyBehavior()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("empty.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
QCOMPARE(x, qreal(200)); //should change immediately
-
- delete rect;
}
void tst_qquickbehaviors::explicitSelection()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("explicit.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
//i.e. the behavior has been triggered
-
- delete rect;
}
void tst_qquickbehaviors::nonSelectingBehavior()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("nonSelecting2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
QCOMPARE(x, qreal(200)); //should change immediately
-
- delete rect;
}
void tst_qquickbehaviors::reassignedAnimation()
@@ -296,27 +269,23 @@ void tst_qquickbehaviors::reassignedAnimation()
QQmlComponent c(&engine, testFileUrl("reassignedAnimation.qml"));
QString warning = testFileUrl("reassignedAnimation.qml").toString() + ":9:9: QML Behavior: Cannot change the animation assigned to a Behavior.";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QCOMPARE(qobject_cast<QQuickNumberAnimation*>(
rect->findChild<QQuickBehavior*>("MyBehavior")->animation())->duration(), 200);
-
- delete rect;
}
void tst_qquickbehaviors::disabled()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("disabled.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QCOMPARE(rect->findChild<QQuickBehavior*>("MyBehavior")->enabled(), false);
- QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickItemPrivate::get(rect.data())->setState("moved");
qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
QCOMPARE(x, qreal(200)); //should change immediately
-
- delete rect;
}
void tst_qquickbehaviors::dontStart()
@@ -327,13 +296,12 @@ void tst_qquickbehaviors::dontStart()
QString warning = c.url().toString() + ":13:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
- QVERIFY(myAnim && !myAnim->qtAnimation());
-
- delete rect;
+ QVERIFY(myAnim);
+ QVERIFY(!myAnim->qtAnimation());
}
void tst_qquickbehaviors::startup()
@@ -341,22 +309,20 @@ void tst_qquickbehaviors::startup()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("startup.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickRectangle *innerRect = rect->findChild<QQuickRectangle*>("innerRect");
QVERIFY(innerRect);
QCOMPARE(innerRect->x(), qreal(100)); //should be set immediately
-
- delete rect;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("startup2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickRectangle *innerRect = rect->findChild<QQuickRectangle*>("innerRect");
QVERIFY(innerRect);
@@ -365,8 +331,6 @@ void tst_qquickbehaviors::startup()
QVERIFY(text);
QCOMPARE(innerRect->x(), text->width()); //should be set immediately
-
- delete rect;
}
}
@@ -375,10 +339,8 @@ void tst_qquickbehaviors::groupedPropertyCrash()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("groupedPropertyCrash.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect); //don't crash
-
- delete rect;
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString())); //don't crash
}
//QTBUG-5491
@@ -386,8 +348,8 @@ void tst_qquickbehaviors::runningTrue()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("runningTrue.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickAbstractAnimation *animation = rect->findChild<QQuickAbstractAnimation*>("rotAnim");
QVERIFY(animation);
@@ -395,8 +357,6 @@ void tst_qquickbehaviors::runningTrue()
QSignalSpy runningSpy(animation, SIGNAL(runningChanged(bool)));
rect->setProperty("myValue", 180);
QTRY_VERIFY(runningSpy.count() > 0);
-
- delete rect;
}
//QTBUG-12295
@@ -404,8 +364,8 @@ void tst_qquickbehaviors::sameValue()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("qtbug12295.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickRectangle *target = rect->findChild<QQuickRectangle*>("myRect");
QVERIFY(target);
@@ -424,8 +384,6 @@ void tst_qquickbehaviors::sameValue()
//even though we set 0 twice in a row.
target->setProperty("x", 0);
QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100));
-
- delete rect;
}
//QTBUG-18362
@@ -434,8 +392,8 @@ void tst_qquickbehaviors::delayedRegistration()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("delayedRegistration.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickItem *innerRect = rect->property("myItem").value<QQuickItem*>();
QVERIFY(innerRect != 0);
@@ -451,8 +409,8 @@ void tst_qquickbehaviors::startOnCompleted()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("startOnCompleted.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickItem *innerRect = rect->findChild<QQuickRectangle*>();
QVERIFY(innerRect != 0);
@@ -460,8 +418,6 @@ void tst_qquickbehaviors::startOnCompleted()
QCOMPARE(innerRect->property("x").toInt(), int(0));
QTRY_COMPARE(innerRect->property("x").toInt(), int(100));
-
- delete rect;
}
//QTBUG-25139
@@ -471,7 +427,7 @@ void tst_qquickbehaviors::multipleChangesToValueType()
QQmlComponent c(&engine, testFileUrl("multipleChangesToValueType.qml"));
QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle *>(c.create()));
- QVERIFY(rect != 0);
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickText *text = rect->findChild<QQuickText *>();
QVERIFY(text != 0);
@@ -496,8 +452,8 @@ void tst_qquickbehaviors::currentValue()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("qtbug21549.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
- QVERIFY(item);
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create()));
+ QVERIFY2(!item.isNull(), qPrintable(c.errorString()));
QQuickRectangle *target = item->findChild<QQuickRectangle*>("myRect");
QVERIFY(target);
@@ -516,15 +472,13 @@ void tst_qquickbehaviors::currentValue()
target->setProperty("x", 100);
QCOMPARE(item->property("behaviorCount").toInt(), 1);
QCOMPARE(target->x(), qreal(100));
-
- delete item;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("qtbug21549-2.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
- QVERIFY(item);
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create()));
+ QVERIFY2(!item.isNull(), qPrintable(c.errorString()));
QQuickRectangle *target = item->findChild<QQuickRectangle*>("myRect");
QVERIFY(target);
@@ -537,9 +491,7 @@ void tst_qquickbehaviors::currentValue()
// in the QML (which should be between 50 and 80);
QTRY_COMPARE(item->property("animRunning").toBool(), true);
QTRY_COMPARE(item->property("animRunning").toBool(), false);
- QVERIFY(target->x() > qreal(50) && target->x() < qreal(80));
-
- delete item;
+ QVERIFY2(target->x() > qreal(50) && target->x() < qreal(80), QByteArray::number(target->x()));
}
}
@@ -548,8 +500,8 @@ void tst_qquickbehaviors::disabledWriteWhileRunning()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("disabledWriteWhileRunning.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
- QVERIFY(root);
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(c.create()));
+ QVERIFY2(!root.isNull(), qPrintable(c.errorString()));
QQuickRectangle *myRect = qobject_cast<QQuickRectangle*>(root->findChild<QQuickRectangle*>("MyRect"));
QQuickBehavior *myBehavior = qobject_cast<QQuickBehavior*>(root->findChild<QQuickBehavior*>("MyBehavior"));
@@ -579,16 +531,14 @@ void tst_qquickbehaviors::disabledWriteWhileRunning()
QCOMPARE(myRect->x(), qreal(100));
QTest::qWait(200);
QCOMPARE(myRect->x(), qreal(100));
-
- delete root;
}
//test additional complications with SmoothedAnimation
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("disabledWriteWhileRunning2.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
- QVERIFY(root);
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(c.create()));
+ QVERIFY2(!root.isNull(), qPrintable(c.errorString()));
QQuickRectangle *myRect = qobject_cast<QQuickRectangle*>(root->findChild<QQuickRectangle*>("MyRect"));
QQuickBehavior *myBehavior = qobject_cast<QQuickBehavior*>(root->findChild<QQuickBehavior*>("MyBehavior"));
@@ -623,8 +573,6 @@ void tst_qquickbehaviors::disabledWriteWhileRunning()
QCOMPARE(myRect->x(), qreal(100));
QTest::qWait(200);
QCOMPARE(myRect->x(), qreal(100));
-
- delete root;
}
}
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index efe2ca8b18..2a96bd1501 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -132,6 +132,13 @@ void tst_qquickborderimage::imageSource()
QFETCH(bool, remote);
QFETCH(QString, error);
+#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
+ if (qstrcmp(QTest::currentDataTag(), "remote") == 0
+ || qstrcmp(QTest::currentDataTag(), "remote not found") == 0) {
+ QSKIP("Remote tests cause occasional hangs in the CI system -- QTBUG-45655");
+ }
+#endif
+
TestHTTPServer server;
if (remote) {
QVERIFY2(server.listen(), qPrintable(server.errorString()));
diff --git a/tests/auto/quick/qquickflickable/BLACKLIST b/tests/auto/quick/qquickflickable/BLACKLIST
index 92ed8708de..647bf819a5 100644
--- a/tests/auto/quick/qquickflickable/BLACKLIST
+++ b/tests/auto/quick/qquickflickable/BLACKLIST
@@ -10,7 +10,7 @@ osx-10.10
osx-10.10
[stopAtBounds]
osx-10.10
-windows 32bit developer-build
+windows developer-build
[returnToBounds]
osx
[pressWhileFlicking]
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 7d08c3c81e..44da9a64e5 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -249,7 +249,7 @@ void tst_qquickflickable::rebound()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -295,11 +295,11 @@ void tst_qquickflickable::rebound()
// flick and trigger the transition multiple times
// (moving signals are emitted as soon as the first transition starts)
- flick(window.data(), QPoint(20,20), QPoint(120,120), 200); // both x and y will bounce back
- flick(window.data(), QPoint(20,120), QPoint(120,20), 200); // only x will bounce back
+ flick(window.data(), QPoint(20,20), QPoint(120,120), 50); // both x and y will bounce back
+ flick(window.data(), QPoint(20,120), QPoint(120,20), 50); // only x will bounce back
QVERIFY(flickable->isMoving());
- QVERIFY(window->rootObject()->property("transitionsStarted").toInt() >= 1);
+ QTRY_VERIFY(window->rootObject()->property("transitionsStarted").toInt() >= 1);
QCOMPARE(hMoveSpy.count(), 1);
QCOMPARE(vMoveSpy.count(), 1);
QCOMPARE(movementStartedSpy.count(), 1);
@@ -388,7 +388,7 @@ void tst_qquickflickable::pressDelay()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -406,7 +406,7 @@ void tst_qquickflickable::pressDelay()
QQuickItem *mouseArea = window->rootObject()->findChild<QQuickItem*>("mouseArea");
QSignalSpy clickedSpy(mouseArea, SIGNAL(clicked(QQuickMouseEvent*)));
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ moveAndPress(window.data(), QPoint(150, 150));
// The press should not occur immediately
QVERIFY(mouseArea->property("pressed").toBool() == false);
@@ -427,7 +427,7 @@ void tst_qquickflickable::pressDelay()
// Test a quick tap within the pressDelay timeout
clickedSpy.clear();
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(180, 180));
+ moveAndPress(window.data(), QPoint(180, 180));
// The press should not occur immediately
QVERIFY(mouseArea->property("pressed").toBool() == false);
@@ -444,7 +444,7 @@ void tst_qquickflickable::pressDelay()
// QTBUG-31168
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 110));
+ moveAndPress(window.data(), QPoint(150, 110));
// The press should not occur immediately
QVERIFY(mouseArea->property("pressed").toBool() == false);
@@ -469,7 +469,7 @@ void tst_qquickflickable::nestedPressDelay()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -478,7 +478,7 @@ void tst_qquickflickable::nestedPressDelay()
QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
QVERIFY(inner != 0);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ moveAndPress(window.data(), QPoint(150, 150));
// the MouseArea is not pressed immediately
QVERIFY(outer->property("pressed").toBool() == false);
QVERIFY(inner->property("pressed").toBool() == false);
@@ -490,7 +490,7 @@ void tst_qquickflickable::nestedPressDelay()
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
// Dragging inner Flickable should work
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(80, 150));
+ moveAndPress(window.data(), QPoint(80, 150));
// the MouseArea is not pressed immediately
QVERIFY(outer->property("pressed").toBool() == false);
QVERIFY(inner->property("pressed").toBool() == false);
@@ -505,7 +505,7 @@ void tst_qquickflickable::nestedPressDelay()
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(20, 150));
// Dragging the MouseArea in the inner Flickable should move the inner Flickable
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ moveAndPress(window.data(), QPoint(150, 150));
// the MouseArea is not pressed immediately
QVERIFY(outer->property("pressed").toBool() == false);
@@ -529,7 +529,7 @@ void tst_qquickflickable::nestedClickThenFlick()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -538,7 +538,7 @@ void tst_qquickflickable::nestedClickThenFlick()
QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
QVERIFY(inner != 0);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ moveAndPress(window.data(), QPoint(150, 150));
// the MouseArea is not pressed immediately
QVERIFY(outer->property("pressed").toBool() == false);
@@ -549,7 +549,7 @@ void tst_qquickflickable::nestedClickThenFlick()
QVERIFY(outer->property("pressed").toBool() == false);
// Dragging inner Flickable should work
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(80, 150));
+ moveAndPress(window.data(), QPoint(80, 150));
// the MouseArea is not pressed immediately
QVERIFY(outer->property("pressed").toBool() == false);
@@ -628,6 +628,8 @@ void tst_qquickflickable::returnToBounds()
window->rootContext()->setContextProperty("setRebound", setRebound);
window->setSource(testFileUrl("resize.qml"));
+ window->show();
+ QTest::qWaitForWindowActive(window.data());
QVERIFY(window->rootObject() != 0);
QQuickFlickable *obj = findItem<QQuickFlickable>(window->rootObject(), "flick");
@@ -671,7 +673,7 @@ void tst_qquickflickable::wheel()
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("wheel.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flick = window->rootObject()->findChild<QQuickFlickable*>("flick");
@@ -740,7 +742,7 @@ void tst_qquickflickable::movingAndFlicking()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -903,7 +905,7 @@ void tst_qquickflickable::movingAndDragging()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -922,7 +924,7 @@ void tst_qquickflickable::movingAndDragging()
QSignalSpy moveEndSpy(flickable, SIGNAL(movementEnded()));
// start the drag
- QTest::mousePress(window.data(), Qt::LeftButton, 0, moveFrom);
+ moveAndPress(window.data(), moveFrom);
QTest::mouseMove(window.data(), moveFrom + moveByWithoutSnapBack);
QTest::mouseMove(window.data(), moveFrom + moveByWithoutSnapBack*2);
QTest::mouseMove(window.data(), moveFrom + moveByWithoutSnapBack*3);
@@ -998,7 +1000,7 @@ void tst_qquickflickable::movingAndDragging()
flickable->setContentX(0);
flickable->setContentY(0);
QTRY_VERIFY(!flickable->isMoving());
- QTest::mousePress(window.data(), Qt::LeftButton, 0, moveFrom);
+ moveAndPress(window.data(), moveFrom);
QTest::mouseMove(window.data(), moveFrom + moveByWithSnapBack);
QTest::mouseMove(window.data(), moveFrom + moveByWithSnapBack*2);
QTest::mouseMove(window.data(), moveFrom + moveByWithSnapBack*3);
@@ -1072,7 +1074,7 @@ void tst_qquickflickable::flickOnRelease()
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("flickable03.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -1085,7 +1087,7 @@ void tst_qquickflickable::flickOnRelease()
// underlying drivers will hopefully provide a pre-calculated velocity
// (based on more data than what the UI gets), thus making this use case
// working even with small movements.
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(50, 300));
+ moveAndPress(window.data(), QPoint(50, 300));
QTest::mouseMove(window.data(), QPoint(50, 10), 10);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 10), 10);
@@ -1109,7 +1111,7 @@ void tst_qquickflickable::pressWhileFlicking()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -1159,13 +1161,13 @@ void tst_qquickflickable::disabled()
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("disabled.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flick = window->rootObject()->findChild<QQuickFlickable*>("flickable");
QVERIFY(flick != 0);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(50, 90));
+ moveAndPress(window.data(), QPoint(50, 90));
QTest::mouseMove(window.data(), QPoint(50, 80));
QTest::mouseMove(window.data(), QPoint(50, 70));
@@ -1176,7 +1178,7 @@ void tst_qquickflickable::disabled()
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 60));
// verify that mouse clicks on other elements still work (QTBUG-20584)
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(50, 10));
+ moveAndPress(window.data(), QPoint(50, 10));
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 10));
QTRY_VERIFY(window->rootObject()->property("clicked").toBool() == true);
@@ -1190,7 +1192,7 @@ void tst_qquickflickable::flickVelocity()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
@@ -1235,7 +1237,7 @@ void tst_qquickflickable::margins()
QQuickViewTestUtil::moveMouseAway(window.data());
window->setTitle(QTest::currentTestFunction());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickItem *root = window->rootObject();
QVERIFY(root);
QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
@@ -1298,13 +1300,13 @@ void tst_qquickflickable::cancelOnMouseGrab()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
QVERIFY(flickable != 0);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10, 10));
+ moveAndPress(window.data(), QPoint(10, 10));
// drag out of bounds
QTest::mouseMove(window.data(), QPoint(50, 50));
QTest::mouseMove(window.data(), QPoint(100, 100));
@@ -1324,7 +1326,7 @@ void tst_qquickflickable::cancelOnMouseGrab()
QTRY_VERIFY(!flickable->isMoving());
QTRY_VERIFY(!flickable->isDragging());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 10));
+ moveAndRelease(window.data(), QPoint(50, 10));
}
@@ -1336,41 +1338,41 @@ void tst_qquickflickable::clickAndDragWhenTransformed()
QQuickViewTestUtil::centerOnScreen(view.data());
QQuickViewTestUtil::moveMouseAway(view.data());
view->show();
- QVERIFY(QTest::qWaitForWindowExposed(view.data()));
+ QVERIFY(QTest::qWaitForWindowActive(view.data()));
QVERIFY(view->rootObject() != 0);
QQuickFlickable *flickable = view->rootObject()->findChild<QQuickFlickable*>("flickable");
QVERIFY(flickable != 0);
// click outside child rect
- QTest::mousePress(view.data(), Qt::LeftButton, 0, QPoint(190, 190));
+ moveAndPress(view.data(), QPoint(190, 190));
QTRY_COMPARE(flickable->property("itemPressed").toBool(), false);
QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(190, 190));
// click inside child rect
- QTest::mousePress(view.data(), Qt::LeftButton, 0, QPoint(200, 200));
+ moveAndPress(view.data(), QPoint(200, 200));
QTRY_COMPARE(flickable->property("itemPressed").toBool(), true);
QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(200, 200));
const int threshold = qApp->styleHints()->startDragDistance();
// drag outside bounds
- QTest::mousePress(view.data(), Qt::LeftButton, 0, QPoint(160, 160));
+ moveAndPress(view.data(), QPoint(160, 160));
QTest::qWait(10);
QTest::mouseMove(view.data(), QPoint(160 + threshold * 2, 160));
QTest::mouseMove(view.data(), QPoint(160 + threshold * 3, 160));
QCOMPARE(flickable->isDragging(), false);
QCOMPARE(flickable->property("itemPressed").toBool(), false);
- QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(180, 160));
+ moveAndRelease(view.data(), QPoint(180, 160));
// drag inside bounds
- QTest::mousePress(view.data(), Qt::LeftButton, 0, QPoint(200, 140));
+ moveAndPress(view.data(), QPoint(200, 140));
QTest::qWait(10);
QTest::mouseMove(view.data(), QPoint(200 + threshold * 2, 140));
QTest::mouseMove(view.data(), QPoint(200 + threshold * 3, 140));
QCOMPARE(flickable->isDragging(), true);
QCOMPARE(flickable->property("itemPressed").toBool(), false);
- QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(220, 140));
+ moveAndRelease(view.data(), QPoint(220, 140));
}
void tst_qquickflickable::flickTwiceUsingTouches()
@@ -1459,7 +1461,7 @@ void tst_qquickflickable::nestedStopAtBounds()
QQuickViewTestUtil::moveMouseAway(&view);
view.show();
view.requestActivate();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(view.rootObject());
QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(view.rootObject());
@@ -1489,7 +1491,7 @@ void tst_qquickflickable::nestedStopAtBounds()
int &axis = transpose ? position.ry() : position.rx();
// drag toward the aligned boundary. Outer flickable dragged.
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ moveAndPress(&view, position);
QTest::qWait(10);
axis += invert ? threshold * 2 : -threshold * 2;
QTest::mouseMove(&view, position);
@@ -1507,7 +1509,7 @@ void tst_qquickflickable::nestedStopAtBounds()
outer->setContentY(50);
// drag away from the aligned boundary. Inner flickable dragged.
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ moveAndPress(&view, position);
QTest::qWait(10);
axis += invert ? -threshold * 2 : threshold * 2;
QTest::mouseMove(&view, position);
@@ -1526,7 +1528,7 @@ void tst_qquickflickable::nestedStopAtBounds()
inner->setContentHeight(inner->height() - margin);
// Drag inner with equal size and contentSize
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ moveAndPress(&view, position);
QTest::qWait(10);
axis += invert ? -threshold * 2 : threshold * 2;
QTest::mouseMove(&view, position);
@@ -1543,7 +1545,7 @@ void tst_qquickflickable::nestedStopAtBounds()
inner->setContentHeight(inner->height() - 100);
// Drag inner with size greater than contentSize
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ moveAndPress(&view, position);
QTest::qWait(10);
axis += invert ? -threshold * 2 : threshold * 2;
QTest::mouseMove(&view, position);
@@ -1583,7 +1585,7 @@ void tst_qquickflickable::stopAtBounds()
QQuickViewTestUtil::moveMouseAway(&view);
view.show();
view.requestActivate();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(view.rootObject());
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(view.rootObject());
@@ -1601,7 +1603,7 @@ void tst_qquickflickable::stopAtBounds()
int &axis = transpose ? position.ry() : position.rx();
// drag away from the aligned boundary. View should not move
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ moveAndPress(&view, position);
QTest::qWait(10);
for (int i = 0; i < 3; ++i) {
axis += invert ? -threshold : threshold;
@@ -1649,12 +1651,14 @@ void tst_qquickflickable::stopAtBounds()
} else {
flickable->setContentX(invert ? 100 : 0);
}
+
+ QSignalSpy flickSignal(flickable, SIGNAL(flickingChanged()));
if (invert)
flick(&view, QPoint(20,20), QPoint(120,120), 100);
else
flick(&view, QPoint(120,120), QPoint(20,20), 100);
- QVERIFY(flickable->isFlicking());
+ QVERIFY(flickSignal.count() > 0);
if (transpose) {
if (invert)
QTRY_COMPARE(flickable->isAtYBeginning(), true);
@@ -1707,11 +1711,11 @@ void tst_qquickflickable::pressDelayWithLoader()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);
// do not crash
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ moveAndPress(window.data(), QPoint(150, 150));
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
}
diff --git a/tests/auto/quick/qquickgridview/BLACKLIST b/tests/auto/quick/qquickgridview/BLACKLIST
new file mode 100644
index 0000000000..9eb9940aa5
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/BLACKLIST
@@ -0,0 +1,2 @@
+[snapOneRow:horizontal, right to left]
+windows
diff --git a/tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml b/tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml
new file mode 100644
index 0000000000..3f8246bafc
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml
@@ -0,0 +1,47 @@
+import QtQuick 2.1
+
+Item {
+ width: 400
+ height: 600
+ function takeOne()
+ {
+ gridView.model.remove(2)
+ }
+ function takeThree()
+ {
+ gridView.model.remove(4)
+ gridView.model.remove(2)
+ gridView.model.remove(0)
+ }
+ function takeAll()
+ {
+ gridView.model.clear()
+ }
+
+ GridView {
+ id: gridView
+
+ property bool useDelayRemove
+
+ height: parent.height
+ width: 400
+ cellWidth: width/2
+ model: ListModel {
+ ListElement { name: "A" }
+ ListElement { name: "B" }
+ ListElement { name: "C" }
+ ListElement { name: "D" }
+ ListElement { name: "E" }
+ }
+ delegate: Text {
+ id: wrapper
+ height: 100
+ text: index + gridView.count
+ GridView.delayRemove: gridView.useDelayRemove
+ GridView.onRemove: SequentialAnimation {
+ PauseAnimation { duration: wrapper.GridView.delayRemove ? 100 : 0 }
+ PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 9472407e01..d53ee00b45 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -206,6 +206,9 @@ private slots:
void jsArrayChange();
+ void contentHeightWithDelayRemove_data();
+ void contentHeightWithDelayRemove();
+
private:
QList<int> toIntList(const QVariantList &list);
void matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes);
@@ -4315,8 +4318,19 @@ void tst_QQuickGridView::snapToRow()
QQuickItem *contentItem = gridview->contentItem();
QTRY_VERIFY(contentItem != 0);
+ qreal origContentY = gridview->contentY();
+ qreal origContentX = gridview->contentX();
// confirm that a flick hits an item boundary
flick(window, flickStart, flickEnd, 180);
+
+ // wait until it's at least one cell further
+ QTRY_VERIFY(qAbs(gridview->contentX() - origContentX) > 80 ||
+ qAbs(gridview->contentY() - origContentY) > 80);
+
+ // click to stop it. Otherwise we wouldn't know how much further it will go. We don't want to it
+ // to hit the endExtent, yet.
+ QTest::mouseClick(window, Qt::LeftButton, 0, flickEnd);
+
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
if (flow == QQuickGridView::FlowLeftToRight)
QCOMPARE(qreal(fmod(gridview->contentY(),80.0)), snapAlignment);
@@ -6460,6 +6474,74 @@ void tst_QQuickGridView::jsArrayChange()
QCOMPARE(spy.count(), 1);
}
+void tst_QQuickGridView::contentHeightWithDelayRemove_data()
+{
+ QTest::addColumn<bool>("useDelayRemove");
+ QTest::addColumn<QByteArray>("removeFunc");
+ QTest::addColumn<int>("countDelta");
+ QTest::addColumn<qreal>("contentHeightDelta");
+
+ QTest::newRow("remove without delayRemove")
+ << false
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with delayRemove")
+ << true
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with multiple delayRemove")
+ << true
+ << QByteArray("takeThree")
+ << -3
+ << qreal(-2 * 100.0);
+
+ QTest::newRow("clear with delayRemove")
+ << true
+ << QByteArray("takeAll")
+ << -5
+ << qreal(-3 * 100.0);
+}
+
+void tst_QQuickGridView::contentHeightWithDelayRemove()
+{
+ QFETCH(bool, useDelayRemove);
+ QFETCH(QByteArray, removeFunc);
+ QFETCH(int, countDelta);
+ QFETCH(qreal, contentHeightDelta);
+
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("contentHeightWithDelayRemove.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickGridView *gridview = window->rootObject()->findChild<QQuickGridView*>();
+ QTRY_VERIFY(gridview != 0);
+
+ const int initialCount(gridview->count());
+ const int eventualCount(initialCount + countDelta);
+
+ const qreal initialContentHeight(gridview->contentHeight());
+ const int eventualContentHeight(qRound(initialContentHeight + contentHeightDelta));
+
+ gridview->setProperty("useDelayRemove", useDelayRemove);
+ QMetaObject::invokeMethod(window->rootObject(), removeFunc.constData());
+ QTest::qWait(50);
+ QCOMPARE(gridview->count(), eventualCount);
+
+ if (useDelayRemove) {
+ QCOMPARE(qRound(gridview->contentHeight()), qRound(initialContentHeight));
+ QTRY_COMPARE(qRound(gridview->contentHeight()), eventualContentHeight);
+ } else {
+ QCOMPARE(qRound(gridview->contentHeight()), eventualContentHeight);
+ }
+
+ delete window;
+}
+
QTEST_MAIN(tst_QQuickGridView)
#include "tst_qquickgridview.moc"
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index ce8b52222d..91ef921141 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -168,6 +168,18 @@ void tst_qquickimage::imageSource()
QFETCH(bool, cache);
QFETCH(QString, error);
+
+#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
+ if (qstrcmp(QTest::currentDataTag(), "remote") == 0
+ || qstrcmp(QTest::currentDataTag(), "remote redirected") == 0
+ || qstrcmp(QTest::currentDataTag(), "remote svg") == 0
+ || qstrcmp(QTest::currentDataTag(), "remote svgz") == 0
+ || qstrcmp(QTest::currentDataTag(), "remote not found") == 0
+ ) {
+ QSKIP("Remote tests cause occasional hangs in the CI system -- QTBUG-45655");
+ }
+#endif
+
TestHTTPServer server;
if (remote) {
QVERIFY2(server.listen(), qPrintable(server.errorString()));
@@ -554,16 +566,17 @@ void tst_qquickimage::noLoading()
QTRY_VERIFY(obj->status() == QQuickImage::Ready);
QTRY_VERIFY(obj->progress() == 1.0);
QTRY_COMPARE(sourceSpy.count(), 2);
- QTRY_COMPARE(progressSpy.count(), 2);
+ QTRY_VERIFY(progressSpy.count() >= 2);
QTRY_COMPARE(statusSpy.count(), 3);
// Loading remote file again - should not go through 'Loading' state.
+ progressSpy.clear();
ctxt->setContextProperty("srcImage", testFileUrl("green.png"));
ctxt->setContextProperty("srcImage", server.url("/rect.png"));
QTRY_VERIFY(obj->status() == QQuickImage::Ready);
QTRY_VERIFY(obj->progress() == 1.0);
QTRY_COMPARE(sourceSpy.count(), 4);
- QTRY_COMPARE(progressSpy.count(), 2);
+ QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 5);
delete obj;
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index dae46b5c3d..80406be753 100644
--- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
+++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
@@ -37,6 +37,7 @@
#include <private/qquickimage_p.h>
#include <QImageReader>
#include <QWaitCondition>
+#include <QThreadPool>
Q_DECLARE_METATYPE(QQuickImageProvider*);
@@ -68,6 +69,8 @@ private slots:
void threadTest();
+ void asyncTextureTest();
+
private:
QString newImageFileName() const;
void fillRequestTestsData(const QString &id);
@@ -457,6 +460,101 @@ void tst_qquickimageprovider::threadTest()
}
}
+class TestImageResponse : public QQuickImageResponse, public QRunnable
+{
+ public:
+ TestImageResponse(QMutex *lock, QWaitCondition *condition, bool *ok, const QString &id, const QSize &requestedSize)
+ : m_lock(lock), m_condition(condition), m_ok(ok), m_id(id), m_requestedSize(requestedSize), m_texture(0)
+ {
+ setAutoDelete(false);
+ }
+
+ QQuickTextureFactory *textureFactory() const
+ {
+ return m_texture;
+ }
+
+ void run()
+ {
+ m_lock->lock();
+ if (!(*m_ok)) {
+ m_condition->wait(m_lock);
+ }
+ m_lock->unlock();
+ QImage image(50, 50, QImage::Format_RGB32);
+ image.fill(QColor(m_id).rgb());
+ if (m_requestedSize.isValid())
+ image = image.scaled(m_requestedSize);
+ m_texture = QQuickTextureFactory::textureFactoryForImage(image);
+ emit finished();
+ }
+
+ QMutex *m_lock;
+ QWaitCondition *m_condition;
+ bool *m_ok;
+ QString m_id;
+ QSize m_requestedSize;
+ QQuickTextureFactory *m_texture;
+};
+
+class TestAsyncProvider : public QQuickAsyncImageProvider
+{
+ public:
+ TestAsyncProvider() : ok(false)
+ {
+ pool.setMaxThreadCount(4);
+ }
+
+ ~TestAsyncProvider() {}
+
+ QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize)
+ {
+ TestImageResponse *response = new TestImageResponse(&lock, &condition, &ok, id, requestedSize);
+ pool.start(response);
+ return response;
+ }
+
+ QThreadPool pool;
+ QMutex lock;
+ QWaitCondition condition;
+ bool ok;
+};
+
+
+void tst_qquickimageprovider::asyncTextureTest()
+{
+ QQmlEngine engine;
+
+ TestAsyncProvider *provider = new TestAsyncProvider;
+
+ engine.addImageProvider("test_async", provider);
+ QVERIFY(engine.imageProvider("test_async") != 0);
+
+ QString componentStr = "import QtQuick 2.0\nItem { \n"
+ "Image { source: \"image://test_async/blue\"; }\n"
+ "Image { source: \"image://test_async/red\"; }\n"
+ "Image { source: \"image://test_async/green\"; }\n"
+ "Image { source: \"image://test_async/yellow\"; }\n"
+ " }";
+ QQmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QObject *obj = component.create();
+ //MUST not deadlock
+ QVERIFY(obj != 0);
+ QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
+ QCOMPARE(images.count(), 4);
+
+ QTRY_VERIFY(provider->pool.activeThreadCount() == 4);
+ foreach (QQuickImage *img, images) {
+ QTRY_VERIFY(img->status() == QQuickImage::Loading);
+ }
+ provider->ok = true;
+ provider->condition.wakeAll();
+ foreach (QQuickImage *img, images) {
+ QTRY_VERIFY(img->status() == QQuickImage::Ready);
+ }
+}
+
QTEST_MAIN(tst_qquickimageprovider)
diff --git a/tests/auto/quick/qquickitem/BLACKLIST b/tests/auto/quick/qquickitem/BLACKLIST
new file mode 100644
index 0000000000..d94a3ef102
--- /dev/null
+++ b/tests/auto/quick/qquickitem/BLACKLIST
@@ -0,0 +1,2 @@
+[contains:hollow square: testing points inside]
+xcb
diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST
new file mode 100644
index 0000000000..269696ce8c
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/BLACKLIST
@@ -0,0 +1,4 @@
+[QTBUG_38209]
+*
+[enforceRange_withoutHighlight]
+osx
diff --git a/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml b/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml
new file mode 100644
index 0000000000..06011519b2
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml
@@ -0,0 +1,46 @@
+import QtQuick 2.1
+
+Item {
+ width: 400
+ height: 600
+ function takeOne()
+ {
+ listView.model.remove(2)
+ }
+ function takeThree()
+ {
+ listView.model.remove(4)
+ listView.model.remove(2)
+ listView.model.remove(0)
+ }
+ function takeAll()
+ {
+ listView.model.clear()
+ }
+
+ ListView {
+ id: listView
+
+ property bool useDelayRemove
+
+ height: parent.height
+ width: 400
+ model: ListModel {
+ ListElement { name: "A" }
+ ListElement { name: "B" }
+ ListElement { name: "C" }
+ ListElement { name: "D" }
+ ListElement { name: "E" }
+ }
+ delegate: Text {
+ id: wrapper
+ height: 100
+ text: index + listView.count
+ ListView.delayRemove: listView.useDelayRemove
+ ListView.onRemove: SequentialAnimation {
+ PauseAnimation { duration: wrapper.ListView.delayRemove ? 100 : 0 }
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/objectmodel.qml b/tests/auto/quick/qquicklistview/data/objectmodel.qml
new file mode 100644
index 0000000000..5c23d64cd3
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/objectmodel.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+import QtQml.Models 2.1
+
+ListView {
+ width: 360
+ height: 360
+ model: ObjectModel {
+ Rectangle {
+ width: 20
+ height: 20
+ color: "red"
+ }
+ Rectangle {
+ width: 20
+ height: 20
+ color: "green"
+ }
+ Rectangle {
+ width: 20
+ height: 20
+ color: "blue"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index c93aac456d..6377650696 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -241,6 +241,10 @@ private slots:
void QTBUG_39492();
void jsArrayChange();
+ void objectModel();
+
+ void contentHeightWithDelayRemove();
+ void contentHeightWithDelayRemove_data();
private:
template <class T> void items(const QUrl &source);
@@ -8063,6 +8067,135 @@ void tst_QQuickListView::jsArrayChange()
QCOMPARE(spy.count(), 1);
}
+static bool compareObjectModel(QQuickListView *listview, QQmlObjectModel *model)
+{
+ if (listview->count() != model->count())
+ return false;
+ for (int i = 0; i < listview->count(); ++i) {
+ listview->setCurrentIndex(i);
+ if (listview->currentItem() != model->get(i))
+ return false;
+ }
+ return true;
+}
+
+void tst_QQuickListView::objectModel()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("objectmodel.qml"));
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(component.create());
+ QVERIFY(listview);
+
+ QQmlObjectModel *model = listview->model().value<QQmlObjectModel *>();
+ QVERIFY(model);
+
+ listview->setCurrentIndex(0);
+ QVERIFY(listview->currentItem());
+ QCOMPARE(listview->currentItem()->property("color").toString(), QColor("red").name());
+
+ listview->setCurrentIndex(1);
+ QVERIFY(listview->currentItem());
+ QCOMPARE(listview->currentItem()->property("color").toString(), QColor("green").name());
+
+ listview->setCurrentIndex(2);
+ QVERIFY(listview->currentItem());
+ QCOMPARE(listview->currentItem()->property("color").toString(), QColor("blue").name());
+
+ QQuickItem *item0 = new QQuickItem(listview);
+ item0->setSize(QSizeF(20, 20));
+ model->append(item0);
+ QCOMPARE(model->count(), 4);
+ QVERIFY(compareObjectModel(listview, model));
+
+ QQuickItem *item1 = new QQuickItem(listview);
+ item1->setSize(QSizeF(20, 20));
+ model->insert(0, item1);
+ QCOMPARE(model->count(), 5);
+ QVERIFY(compareObjectModel(listview, model));
+
+ model->move(1, 2, 3);
+ QVERIFY(compareObjectModel(listview, model));
+
+ model->remove(2, 2);
+ QCOMPARE(model->count(), 3);
+ QVERIFY(compareObjectModel(listview, model));
+
+ model->clear();
+ QCOMPARE(model->count(), 0);
+ QCOMPARE(listview->count(), 0);
+
+ delete listview;
+}
+
+void tst_QQuickListView::contentHeightWithDelayRemove_data()
+{
+ QTest::addColumn<bool>("useDelayRemove");
+ QTest::addColumn<QByteArray>("removeFunc");
+ QTest::addColumn<int>("countDelta");
+ QTest::addColumn<qreal>("contentHeightDelta");
+
+ QTest::newRow("remove without delayRemove")
+ << false
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with delayRemove")
+ << true
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with multiple delayRemove")
+ << true
+ << QByteArray("takeThree")
+ << -3
+ << qreal(-3 * 100.0);
+
+ QTest::newRow("clear with delayRemove")
+ << true
+ << QByteArray("takeAll")
+ << -5
+ << qreal(-5 * 100.0);
+}
+
+void tst_QQuickListView::contentHeightWithDelayRemove()
+{
+ QFETCH(bool, useDelayRemove);
+ QFETCH(QByteArray, removeFunc);
+ QFETCH(int, countDelta);
+ QFETCH(qreal, contentHeightDelta);
+
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("contentHeightWithDelayRemove.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
+ QTRY_VERIFY(listview != 0);
+
+ const int initialCount(listview->count());
+ const int eventualCount(initialCount + countDelta);
+
+ const qreal initialContentHeight(listview->contentHeight());
+ const int eventualContentHeight(qRound(initialContentHeight + contentHeightDelta));
+
+ listview->setProperty("useDelayRemove", useDelayRemove);
+ QMetaObject::invokeMethod(window->rootObject(), removeFunc.constData());
+ QTest::qWait(50);
+ QCOMPARE(listview->count(), eventualCount);
+
+ if (useDelayRemove) {
+ QCOMPARE(qRound(listview->contentHeight()), qRound(initialContentHeight));
+ QTRY_COMPARE(qRound(listview->contentHeight()), eventualContentHeight);
+ } else {
+ QCOMPARE(qRound(listview->contentHeight()), eventualContentHeight);
+ }
+
+ delete window;
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
new file mode 100644
index 0000000000..1777af9e0c
--- /dev/null
+++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
@@ -0,0 +1,2 @@
+[inFlickable]
+*
diff --git a/tests/auto/quick/qquickpathview/data/customAttribute.qml b/tests/auto/quick/qquickpathview/data/customAttribute.qml
new file mode 100644
index 0000000000..bd4c9fd1de
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/customAttribute.qml
@@ -0,0 +1,58 @@
+import QtQuick 2.4
+
+PathView {
+ width: 200
+ height: 600
+
+ pathItemCount: 7
+
+ model: ListModel {
+ ListElement { color: "salmon" }
+ ListElement { color: "seagreen" }
+ ListElement { color: "navy" }
+ ListElement { color: "goldenrod" }
+ }
+ path: Path {
+ startX: width / 2; startY: -100
+ PathAttribute { name: "BEGIN" }
+
+ PathLine { relativeX: 0; y: height / 2 }
+ PathAttribute { name: "BEGIN" }
+
+ PathLine { relativeX: 0; y: height + 100 }
+ PathAttribute { name: "BEGIN" }
+ }
+ delegate: Rectangle {
+ width: 200
+ height: 200
+ color: model.color
+ opacity: PathView.transparency
+ }
+
+ Component {
+ id: attributeComponent
+ PathAttribute {}
+ }
+
+ function addAttribute(name, values) {
+ var valueIndex = 0
+ var elements = []
+ for (var i = 0; i < path.pathElements.length; ++i) {
+ elements.push(path.pathElements[i])
+
+ if (path.pathElements[i].name === "BEGIN") {
+ if (values[valueIndex] !== undefined) {
+ var attribute = attributeComponent.createObject(this, { "name": name, "value": values[valueIndex] })
+ elements.push(attribute)
+ }
+ ++valueIndex
+ }
+ }
+
+ console.log("??")
+ path.pathElements = elements
+ console.log("!!")
+ }
+
+ Component.onCompleted: addAttribute("transparency", [0, 1, 0])
+}
diff --git a/tests/auto/quick/qquickpathview/data/qtbug42716.qml b/tests/auto/quick/qquickpathview/data/qtbug42716.qml
new file mode 100644
index 0000000000..81d52d5ea3
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/qtbug42716.qml
@@ -0,0 +1,111 @@
+import QtQuick 2.0
+
+Rectangle {
+ //Note that this file was originally the manual reproduction, MouseAreas were left in.
+ id: qmlBrowser
+
+ width: 500
+ height: 350
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones 0"
+ }
+ ListElement {
+ name: "Jane Doe 1"
+ }
+ ListElement {
+ name: "John Smith 2"
+ }
+ ListElement {
+ name: "Bill Jones 3"
+ }
+ ListElement {
+ name: "Jane Doe 4"
+ }
+ ListElement {
+ name: "John Smith 5"
+ }
+ ListElement {
+ name: "John Smith 6"
+ }
+ ListElement {
+ name: "John Smith 7"
+ }
+ }
+
+ Component {
+ id: delegate
+
+ Text {
+ id: nameText
+ height: 33
+ width: parent.width
+ objectName: "delegate"+index
+
+ text: "index: " + index + " text: " + name
+ font.pointSize: 16
+ color: PathView.isCurrentItem ? "red" : "black"
+ }
+ }
+
+ PathView {
+ id: contentList
+ objectName: "pathView"
+ anchors.fill: parent
+
+ property int maxPathItemCount: 7
+ property real itemHeight: 34
+
+ delegate: delegate
+ model: myModel
+ currentIndex: 5
+ pathItemCount: maxPathItemCount
+ highlightMoveDuration: 0
+
+ path: Path {
+ startX: 30 + contentList.width / 2
+ startY: 30
+ PathLine {
+ relativeX: 0
+ relativeY: contentList.itemHeight * contentList.maxPathItemCount
+ }
+ }
+
+ focus: true
+ Keys.onLeftPressed: decrementCurrentIndex()
+ Keys.onRightPressed: incrementCurrentIndex()
+ }
+
+ Column {
+ anchors.right: parent.right
+ Text {
+ text: "Go 1"
+ font.weight: Font.Bold
+ font.pixelSize: 24
+ MouseArea {
+ anchors.fill: parent
+ onClicked: contentList.offset = 2.55882
+ }
+ }
+ Text {
+ text: "Go 2"
+ font.weight: Font.Bold
+ font.pixelSize: 24
+ MouseArea {
+ anchors.fill: parent
+ onClicked: contentList.offset = 0.0882353
+ }
+ }
+ Text {
+ text: "Go 3"
+ font.weight: Font.Bold
+ font.pixelSize: 24
+ MouseArea {
+ anchors.fill: parent
+ onClicked: contentList.offset = 0.99987
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 7db15522b5..5636b312af 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -140,6 +140,8 @@ private slots:
void nestedinFlickable();
void flickableDelegate();
void jsArrayChange();
+ void qtbug42716();
+ void addCustomAttribute();
};
class TestObject : public QObject
@@ -2322,6 +2324,61 @@ void tst_QQuickPathView::jsArrayChange()
QCOMPARE(spy.count(), 1);
}
+/* This bug was one where if you jump the list such that the sole missing item needed to be
+ * added in the middle of the list, it would instead move an item somewhere else in the list
+ * to the middle (messing it up very badly).
+ *
+ * The test checks correct visual order both before and after the jump.
+ */
+void tst_QQuickPathView::qtbug42716()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("qtbug42716.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QCOMPARE(window.data(), qGuiApp->focusWindow());
+
+ QQuickPathView *pathView = findItem<QQuickPathView>(window->rootObject(), "pathView");
+ QVERIFY(pathView != 0);
+
+ int order1[] = {5,6,7,0,1,2,3};
+ int missing1 = 4;
+ int order2[] = {0,1,2,3,4,5,6};
+ int missing2 = 7;
+
+ qreal lastY = 0.0;
+ for (int i = 0; i<7; i++) {
+ QQuickItem *item = findItem<QQuickItem>(pathView, QString("delegate%1").arg(order1[i]));
+ QVERIFY(item);
+ QVERIFY(item->y() > lastY);
+ lastY = item->y();
+ }
+ QQuickItem *itemMiss = findItem<QQuickItem>(pathView, QString("delegate%1").arg(missing1));
+ QVERIFY(!itemMiss);
+
+ pathView->setOffset(0.0882353);
+ //Note refill is delayed, needs time to take effect
+ QTest::qWait(100);
+
+ lastY = 0.0;
+ for (int i = 0; i<7; i++) {
+ QQuickItem *item = findItem<QQuickItem>(pathView, QString("delegate%1").arg(order2[i]));
+ QVERIFY(item);
+ QVERIFY(item->y() > lastY);
+ lastY = item->y();
+ }
+ itemMiss = findItem<QQuickItem>(pathView, QString("delegate%1").arg(missing2));
+ QVERIFY(!itemMiss);
+}
+
+void tst_QQuickPathView::addCustomAttribute()
+{
+ const QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("customAttribute.qml"));
+ window->show();
+}
+
QTEST_MAIN(tst_QQuickPathView)
#include "tst_qquickpathview.moc"
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index b9f93a4dcf..584cb78d3d 100644
--- a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
+++ b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
@@ -110,12 +110,14 @@ void tst_qquickpixmapcache::initTestCase()
QVERIFY2(server.listen(), qPrintable(server.errorString()));
+#ifndef QT_NO_BEARERMANAGEMENT
// This avoids a race condition/deadlock bug in network config
// manager when it is accessed by the HTTP server thread before
// anything else. Bug report can be found at:
// QTBUG-26355
QNetworkConfigurationManager cm;
cm.updateConfigurations();
+#endif
server.serveDirectory(testFile("http"));
}
diff --git a/tests/auto/quick/qquickpositioners/data/allInvisible.qml b/tests/auto/quick/qquickpositioners/data/allInvisible.qml
index 5894171434..3b95a5e1da 100644
--- a/tests/auto/quick/qquickpositioners/data/allInvisible.qml
+++ b/tests/auto/quick/qquickpositioners/data/allInvisible.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.6
Item{
width: 400
@@ -41,4 +41,42 @@ Item{
visible: false
}
}
+ Grid{
+ spacing: 20
+ objectName: "grid"
+ Item{
+ width: 0
+ height: 20
+ visible: false
+ }
+ Item{
+ width: 20
+ height: 0
+ visible: false
+ }
+ Item{
+ width: 20
+ height: 20
+ visible: false
+ }
+ }
+ Flow{
+ spacing: 20
+ objectName: "flow"
+ Item{
+ width: 0
+ height: 20
+ visible: false
+ }
+ Item{
+ width: 20
+ height: 0
+ visible: false
+ }
+ Item{
+ width: 20
+ height: 20
+ visible: false
+ }
+ }
}
diff --git a/tests/auto/quick/qquickpositioners/data/flowtest-padding.qml b/tests/auto/quick/qquickpositioners/data/flowtest-padding.qml
new file mode 100644
index 0000000000..a85e7a5c52
--- /dev/null
+++ b/tests/auto/quick/qquickpositioners/data/flowtest-padding.qml
@@ -0,0 +1,44 @@
+import QtQuick 2.6
+
+Item {
+ width: 90
+ height: 480
+ property bool testRightToLeft: false
+
+ Flow {
+ objectName: "flow"
+ width: parent.width
+ layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight
+ padding: 1; topPadding: 2; leftPadding: 3; rightPadding: 4; bottomPadding: 5
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rectangle {
+ objectName: "three"
+ color: "blue"
+ width: 50
+ height: 20
+ }
+ Rectangle {
+ objectName: "four"
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "five"
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpositioners/data/gridtest-padding.qml b/tests/auto/quick/qquickpositioners/data/gridtest-padding.qml
new file mode 100644
index 0000000000..46244ecef5
--- /dev/null
+++ b/tests/auto/quick/qquickpositioners/data/gridtest-padding.qml
@@ -0,0 +1,47 @@
+import QtQuick 2.6
+
+Item {
+ width: 640
+ height: 480
+ property bool testRightToLeft: false
+ property int testHAlignment: Grid.AlignLeft;
+ property int testVAlignment: Grid.AlignTop;
+ Grid {
+ layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight
+ horizontalItemAlignment: testHAlignment
+ verticalItemAlignment: testVAlignment
+ objectName: "grid"
+ columns: 3
+ padding: 1; topPadding: 1; leftPadding: 1; rightPadding: 1; bottomPadding: 1
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rectangle {
+ objectName: "three"
+ color: "blue"
+ width: 30
+ height: 20
+ }
+ Rectangle {
+ objectName: "four"
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "five"
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpositioners/data/horizontal-padding.qml b/tests/auto/quick/qquickpositioners/data/horizontal-padding.qml
new file mode 100644
index 0000000000..d320c4789f
--- /dev/null
+++ b/tests/auto/quick/qquickpositioners/data/horizontal-padding.qml
@@ -0,0 +1,30 @@
+import QtQuick 2.6
+
+Item {
+ width: 640
+ height: 480
+ property bool testRightToLeft: false
+ Row {
+ objectName: "row"
+ layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight
+ padding: 1; topPadding: 1; leftPadding: 1; rightPadding: 1; bottomPadding: 1
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rectangle {
+ objectName: "three"
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpositioners/data/repeatertest-padding.qml b/tests/auto/quick/qquickpositioners/data/repeatertest-padding.qml
new file mode 100644
index 0000000000..577d4ef0b7
--- /dev/null
+++ b/tests/auto/quick/qquickpositioners/data/repeatertest-padding.qml
@@ -0,0 +1,53 @@
+import QtQuick 2.6
+
+Item {
+ width: 640
+ height: 480
+ Row {
+ padding: 1; topPadding: 2; leftPadding: 3; rightPadding: 4; bottomPadding: 5
+ Repeater{ model: 3;
+ delegate: Component {
+ Rectangle {
+ color: "red"
+ width: 50
+ height: 50
+ z: {
+ if (index == 0)
+ return 2;
+ else if (index == 1)
+ return 1;
+ else
+ return 3;
+ }
+ objectName: {
+ if (index == 0)
+ return "one";
+ else if (index == 1)
+ return "two";
+ else
+ return "three";
+ }
+ }
+ }
+ }
+ }
+
+ //This crashed once (QTBUG-16959) because the repeater ended up on the end of the list
+ //If this grid just instantiates without crashing, then it has not regressed.
+ Grid {
+ id: grid
+ rows: 2
+ flow: Grid.TopToBottom
+
+ Repeater {
+ model: 13
+ Rectangle {
+ color: "goldenrod"
+ width: 100
+ height: 100
+ radius: 10
+ border.width: 1
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpositioners/data/repeatertest.qml b/tests/auto/quick/qquickpositioners/data/repeatertest.qml
index d90e1cf160..ae3d961c75 100644
--- a/tests/auto/quick/qquickpositioners/data/repeatertest.qml
+++ b/tests/auto/quick/qquickpositioners/data/repeatertest.qml
@@ -10,8 +10,22 @@ Item {
color: "red"
width: 50
height: 50
- z: {if(index == 0){2;}else if(index == 1){1;} else{3;}}
- objectName: {if(index == 0){"one";}else if(index == 1){"two";} else{"three";}}
+ z: {
+ if (index == 0)
+ return 2;
+ else if (index == 1)
+ return 1;
+ else
+ return 3;
+ }
+ objectName: {
+ if (index == 0)
+ return "one";
+ else if (index == 1)
+ return "two";
+ else
+ return "three";
+ }
}
}
}
diff --git a/tests/auto/quick/qquickpositioners/data/transitions-padding.qml b/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
new file mode 100644
index 0000000000..e3175c480c
--- /dev/null
+++ b/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
@@ -0,0 +1,239 @@
+import QtQuick 2.6
+
+Rectangle {
+ id: root
+ width: 500
+ height: 500
+
+ property int duration: 50
+
+ property real incrementalSize: 5
+
+ property int populateTransitionsDone
+ property int addTransitionsDone
+ property int displaceTransitionsDone
+
+ property var targetTrans_items: new Object()
+ property var targetTrans_targetIndexes: new Array()
+ property var targetTrans_targetItems: new Array()
+
+ property var displacedTrans_items: new Object()
+ property var displacedTrans_targetIndexes: new Array()
+ property var displacedTrans_targetItems: new Array()
+
+ // for QQmlListProperty types
+ function copyList(propList) {
+ var temp = new Array()
+ for (var i=0; i<propList.length; i++)
+ temp.push(propList[i])
+ return temp
+ }
+
+ function checkPos(x, y, name) {
+ if (Qt.point(x, y) == targetItems_transitionFrom)
+ model_targetItems_transitionFrom.addItem(name, "")
+ if (Qt.point(x, y) == displacedItems_transitionVia)
+ model_displacedItems_transitionVia.addItem(name, "")
+ }
+
+ Component.onCompleted: {
+ if (dynamicallyPopulate) {
+ for (var i=0; i<30; i++)
+ testModel.addItem("item " + i, "")
+ }
+ }
+
+ Transition {
+ id: populateTransition
+ enabled: usePopulateTransition
+
+ SequentialAnimation {
+ ScriptAction {
+ script: {
+ root.targetTrans_items[populateTransition.ViewTransition.item.nameData] = populateTransition.ViewTransition.index
+ root.targetTrans_targetIndexes.push(populateTransition.ViewTransition.targetIndexes)
+ root.targetTrans_targetItems.push(root.copyList(populateTransition.ViewTransition.targetItems))
+ }
+ }
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; from: targetItems_transitionFrom.x; duration: root.duration }
+ NumberAnimation { properties: "y"; from: targetItems_transitionFrom.y; duration: root.duration }
+ }
+
+ ScriptAction { script: root.populateTransitionsDone += 1 }
+ }
+ }
+
+ Transition {
+ id: addTransition
+ enabled: enableAddTransition
+
+ SequentialAnimation {
+ ScriptAction {
+ script: {
+ root.targetTrans_items[addTransition.ViewTransition.item.nameData] = addTransition.ViewTransition.index
+ root.targetTrans_targetIndexes.push(addTransition.ViewTransition.targetIndexes)
+ root.targetTrans_targetItems.push(root.copyList(addTransition.ViewTransition.targetItems))
+ }
+ }
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; from: targetItems_transitionFrom.x; duration: root.duration }
+ NumberAnimation { properties: "y"; from: targetItems_transitionFrom.y; duration: root.duration }
+ }
+
+ ScriptAction { script: root.addTransitionsDone += 1 }
+ }
+ }
+
+ Transition {
+ id: displaced
+
+ SequentialAnimation {
+ ScriptAction {
+ script: {
+ root.displacedTrans_items[displaced.ViewTransition.item.nameData] = displaced.ViewTransition.index
+ root.displacedTrans_targetIndexes.push(displaced.ViewTransition.targetIndexes)
+ root.displacedTrans_targetItems.push(root.copyList(displaced.ViewTransition.targetItems))
+ }
+ }
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; duration: root.duration; to: displacedItems_transitionVia.x }
+ NumberAnimation { properties: "y"; duration: root.duration; to: displacedItems_transitionVia.y }
+ }
+ NumberAnimation { properties: "x,y"; duration: root.duration }
+
+ ScriptAction { script: root.displaceTransitionsDone += 1 }
+ }
+
+ }
+
+ Row {
+ objectName: "row"
+
+ property int count: children.length - 1 // omit Repeater
+
+ x: 50; y: 50
+ width: 400; height: 400
+ padding: 1; topPadding: 2; leftPadding: 3; rightPadding: 4; bottomPadding: 5
+ Repeater {
+ objectName: "repeater"
+ model: testedPositioner == "row" ? testModel : undefined
+ Rectangle {
+ property string nameData: name
+ objectName: "wrapper"
+ width: 30 + index*root.incrementalSize
+ height: 30 + index*root.incrementalSize
+ border.width: 1
+ Column {
+ Text { text: index }
+ Text { objectName: "name"; text: name }
+ Text { text: parent.parent.y }
+ }
+ onXChanged: root.checkPos(x, y, name)
+ onYChanged: root.checkPos(x, y, name)
+ }
+ }
+
+ populate: populateTransition
+ add: addTransition
+ move: displaced
+ }
+
+ Column {
+ objectName: "column"
+
+ property int count: children.length - 1 // omit Repeater
+
+ x: 50; y: 50
+ width: 400; height: 400
+ padding: 1; topPadding: 2; leftPadding: 3; rightPadding: 4; bottomPadding: 5
+ Repeater {
+ objectName: "repeater"
+ model: testedPositioner == "column" ? testModel : undefined
+ Rectangle {
+ property string nameData: name
+ objectName: "wrapper"
+ width: 30 + index*root.incrementalSize
+ height: 30 + index*root.incrementalSize
+ border.width: 1
+ Column {
+ Text { text: index }
+ Text { objectName: "name"; text: name }
+ Text { text: parent.parent.y }
+ }
+ onXChanged: root.checkPos(x, y, name)
+ onYChanged: root.checkPos(x, y, name)
+ }
+ }
+
+ populate: populateTransition
+ add: addTransition
+ move: displaced
+ }
+
+ Grid {
+ objectName: "grid"
+
+ property int count: children.length - 1 // omit Repeater
+
+ x: 50; y: 50
+ width: 400; height: 400
+ padding: 1; topPadding: 2; leftPadding: 3; rightPadding: 4; bottomPadding: 5
+ Repeater {
+ objectName: "repeater"
+ model: testedPositioner == "grid" ? testModel : undefined
+ Rectangle {
+ property string nameData: name
+ objectName: "wrapper"
+ width: 30 + index*root.incrementalSize
+ height: 30 + index*root.incrementalSize
+ border.width: 1
+ Column {
+ Text { text: index }
+ Text { objectName: "name"; text: name }
+ Text { text: parent.parent.y }
+ }
+
+ onXChanged: root.checkPos(x, y, name)
+ onYChanged: root.checkPos(x, y, name)
+ }
+ }
+
+ populate: populateTransition
+ add: addTransition
+ move: displaced
+ }
+
+ Flow {
+ objectName: "flow"
+
+ property int count: children.length - 1 // omit Repeater
+
+ x: 50; y: 50
+ width: 400; height: 400
+ padding: 1; topPadding: 2; leftPadding: 3; rightPadding: 4; bottomPadding: 5
+ Repeater {
+ objectName: "repeater"
+ model: testedPositioner == "flow" ? testModel : undefined
+ Rectangle {
+ property string nameData: name
+ objectName: "wrapper"
+ width: 30 + index*root.incrementalSize
+ height: 30 + index*root.incrementalSize
+ border.width: 1
+ Column {
+ Text { text: index }
+ Text { objectName: "name"; text: name }
+ Text { text: parent.parent.x + " " + parent.parent.y }
+ }
+ onXChanged: root.checkPos(x, y, name)
+ onYChanged: root.checkPos(x, y, name)
+ }
+ }
+
+ populate: populateTransition
+ add: addTransition
+ move: displaced
+ }
+}
+
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index 3c44041ca5..c68f58383b 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -53,33 +53,50 @@ public:
private slots:
void test_horizontal();
+ void test_horizontal_padding();
void test_horizontal_rtl();
void test_horizontal_spacing();
void test_horizontal_spacing_rightToLeft();
void test_horizontal_animated();
+ void test_horizontal_animated_padding();
void test_horizontal_animated_rightToLeft();
+ void test_horizontal_animated_rightToLeft_padding();
void test_horizontal_animated_disabled();
+ void test_horizontal_animated_disabled_padding();
void test_vertical();
+ void test_vertical_padding();
void test_vertical_spacing();
void test_vertical_animated();
+ void test_vertical_animated_padding();
void test_grid();
+ void test_grid_padding();
void test_grid_topToBottom();
void test_grid_rightToLeft();
void test_grid_spacing();
void test_grid_row_column_spacing();
void test_grid_animated();
+ void test_grid_animated_padding();
void test_grid_animated_rightToLeft();
+ void test_grid_animated_rightToLeft_padding();
void test_grid_zero_columns();
void test_grid_H_alignment();
+ void test_grid_H_alignment_padding();
void test_grid_V_alignment();
+ void test_grid_V_alignment_padding();
void test_propertychanges();
void test_repeater();
+ void test_repeater_padding();
void test_flow();
+ void test_flow_padding();
void test_flow_rightToLeft();
void test_flow_topToBottom();
+ void test_flow_topToBottom_padding();
void test_flow_resize();
+ void test_flow_resize_padding();
void test_flow_resize_rightToLeft();
+ void test_flow_resize_rightToLeft_padding();
void test_flow_implicit_resize();
+ void test_flow_implicit_resize_padding();
void test_conflictinganchors();
void test_mirroring();
void test_allInvisible();
@@ -198,18 +215,25 @@ void tst_qquickpositioners::addTransitions_grid_data()
// (adding items further down the grid can cause displace transitions at
// previous indexes, since grid is auto-resized to tightly fit all of its items)
+ QTest::addColumn<QString>("qmlFile");
QTest::addColumn<int>("initialItemCount");
QTest::addColumn<int>("insertionIndex");
QTest::addColumn<int>("insertionCount");
QTest::addColumn<ListRange>("expectedDisplacedIndexes");
- QTest::newRow("add one @ start") << 10 << 0 << 1 << ListRange(0, 9);
- QTest::newRow("add one @ middle") << 10 << 5 << 1 << ListRange(3, 3) + ListRange(5, 9);
- QTest::newRow("add one @ end") << 10 << 10 << 1 << ListRange(3, 3) + ListRange(7, 7);
+ QTest::newRow("add one @ start") << "transitions.qml" << 10 << 0 << 1 << ListRange(0, 9);
+ QTest::newRow("add one @ middle") << "transitions.qml" << 10 << 5 << 1 << ListRange(3, 3) + ListRange(5, 9);
+ QTest::newRow("add one @ end") << "transitions.qml" << 10 << 10 << 1 << ListRange(3, 3) + ListRange(7, 7);
+ QTest::newRow("padding, add one @ start") << "transitions-padding.qml" << 10 << 0 << 1 << ListRange(0, 9);
+ QTest::newRow("padding, add one @ middle") << "transitions-padding.qml" << 10 << 5 << 1 << ListRange(3, 3) + ListRange(5, 9);
+ QTest::newRow("padding, add one @ end") << "transitions-padding.qml" << 10 << 10 << 1 << ListRange(3, 3) + ListRange(7, 7);
- QTest::newRow("add multiple @ start") << 10 << 0 << 3 << ListRange(0, 9);
- QTest::newRow("add multiple @ middle") << 10 << 5 << 3 << ListRange(1, 3) + ListRange(5, 9);
- QTest::newRow("add multiple @ end") << 10 << 10 << 3 << ListRange(1, 3) + ListRange(5, 7) + ListRange(9, 9);
+ QTest::newRow("add multiple @ start") << "transitions.qml" << 10 << 0 << 3 << ListRange(0, 9);
+ QTest::newRow("add multiple @ middle") << "transitions.qml" << 10 << 5 << 3 << ListRange(1, 3) + ListRange(5, 9);
+ QTest::newRow("add multiple @ end") << "transitions.qml" << 10 << 10 << 3 << ListRange(1, 3) + ListRange(5, 7) + ListRange(9, 9);
+ QTest::newRow("padding, add multiple @ start") << "transitions-padding.qml" << 10 << 0 << 3 << ListRange(0, 9);
+ QTest::newRow("padding, add multiple @ middle") << "transitions-padding.qml" << 10 << 5 << 3 << ListRange(1, 3) + ListRange(5, 9);
+ QTest::newRow("padding, add multiple @ end") << "transitions-padding.qml" << 10 << 10 << 3 << ListRange(1, 3) + ListRange(5, 7) + ListRange(9, 9);
}
void tst_qquickpositioners::addTransitions_flow()
@@ -253,17 +277,24 @@ void tst_qquickpositioners::moveTransitions_grid_data()
// (removing items further down the grid can cause displace transitions at
// previous indexes, since grid is auto-resized to tightly fit all of its items)
+ QTest::addColumn<QString>("qmlFile");
QTest::addColumn<int>("initialItemCount");
QTest::addColumn<ListChange>("change");
QTest::addColumn<ListRange>("expectedDisplacedIndexes");
- QTest::newRow("remove one @ start") << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
- QTest::newRow("remove one @ middle") << 10 << ListChange::remove(4, 1) << ListRange(2, 3) + ListRange(5, 9);
- QTest::newRow("remove one @ end") << 10 << ListChange::remove(9, 1) << ListRange(2, 3) + ListRange(6, 7);
+ QTest::newRow("remove one @ start") << "transitions.qml" << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
+ QTest::newRow("remove one @ middle") << "transitions.qml" << 10 << ListChange::remove(4, 1) << ListRange(2, 3) + ListRange(5, 9);
+ QTest::newRow("remove one @ end") << "transitions.qml" << 10 << ListChange::remove(9, 1) << ListRange(2, 3) + ListRange(6, 7);
+ QTest::newRow("padding, remove one @ start") << "transitions-padding.qml" << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
+ QTest::newRow("padding, remove one @ middle") << "transitions-padding.qml" << 10 << ListChange::remove(4, 1) << ListRange(2, 3) + ListRange(5, 9);
+ QTest::newRow("padding, remove one @ end") << "transitions-padding.qml" << 10 << ListChange::remove(9, 1) << ListRange(2, 3) + ListRange(6, 7);
- QTest::newRow("remove multiple @ start") << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
- QTest::newRow("remove multiple @ middle") << 10 << ListChange::remove(4, 3) << ListRange(1, 3) + ListRange(7, 9);
- QTest::newRow("remove multiple @ end") << 10 << ListChange::remove(7, 3) << ListRange(1, 3) + ListRange(5, 6);
+ QTest::newRow("remove multiple @ start") << "transitions.qml" << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
+ QTest::newRow("remove multiple @ middle") << "transitions.qml" << 10 << ListChange::remove(4, 3) << ListRange(1, 3) + ListRange(7, 9);
+ QTest::newRow("remove multiple @ end") << "transitions.qml" << 10 << ListChange::remove(7, 3) << ListRange(1, 3) + ListRange(5, 6);
+ QTest::newRow("padding, remove multiple @ start") << "transitions-padding.qml" << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
+ QTest::newRow("padding, remove multiple @ middle") << "transitions-padding.qml" << 10 << ListChange::remove(4, 3) << ListRange(1, 3) + ListRange(7, 9);
+ QTest::newRow("padding, remove multiple @ end") << "transitions-padding.qml" << 10 << ListChange::remove(7, 3) << ListRange(1, 3) + ListRange(5, 6);
}
void tst_qquickpositioners::moveTransitions_flow()
@@ -305,6 +336,185 @@ void tst_qquickpositioners::test_horizontal()
QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
QCOMPARE(row->width(), 110.0);
QCOMPARE(row->height(), 50.0);
+
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->width(), 117.0);
+ QCOMPARE(row->height(), 57.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+}
+
+void tst_qquickpositioners::test_horizontal_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("horizontal.qml")));
+
+ window->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+
+ QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
+ QCOMPARE(row->width(), 110.0);
+ QCOMPARE(row->height(), 50.0);
+
+ QQuickRow *obj = qobject_cast<QQuickRow*>(row);
+ QVERIFY(obj != 0);
+
+ QCOMPARE(row->property("padding").toDouble(), 0.0);
+ QCOMPARE(row->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(row->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(row->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(row->property("bottomPadding").toDouble(), 0.0);
+
+ obj->setPadding(1.0);
+
+ QCOMPARE(row->property("padding").toDouble(), 1.0);
+ QCOMPARE(row->property("topPadding").toDouble(), 1.0);
+ QCOMPARE(row->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(row->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(row->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(row->width(), 112.0);
+ QCOMPARE(row->height(), 52.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 1.0);
+ QCOMPARE(two->x(), 51.0);
+ QCOMPARE(two->y(), 1.0);
+ QCOMPARE(three->x(), 71.0);
+ QCOMPARE(three->y(), 1.0);
+
+ obj->setTopPadding(2.0);
+
+ QCOMPARE(row->property("padding").toDouble(), 1.0);
+ QCOMPARE(row->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(row->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(row->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(row->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(row->height(), 53.0);
+ QCOMPARE(row->width(), 112.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 51.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 71.0);
+ QCOMPARE(three->y(), 2.0);
+
+ obj->setLeftPadding(3.0);
+
+ QCOMPARE(row->property("padding").toDouble(), 1.0);
+ QCOMPARE(row->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(row->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(row->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(row->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(row->width(), 114.0);
+ QCOMPARE(row->height(), 53.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+
+ obj->setRightPadding(4.0);
+
+ QCOMPARE(row->property("padding").toDouble(), 1.0);
+ QCOMPARE(row->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(row->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(row->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(row->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(row->width(), 117.0);
+ QCOMPARE(row->height(), 53.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+
+ obj->setBottomPadding(5.0);
+
+ QCOMPARE(row->property("padding").toDouble(), 1.0);
+ QCOMPARE(row->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(row->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(row->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(row->property("bottomPadding").toDouble(), 5.0);
+
+ QTRY_COMPARE(row->height(), 57.0);
+ QCOMPARE(row->width(), 117.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+
+ obj->resetBottomPadding();
+ QCOMPARE(row->property("bottomPadding").toDouble(), 1.0);
+ QTRY_COMPARE(row->height(), 53.0);
+ QCOMPARE(row->width(), 117.0);
+
+ obj->resetRightPadding();
+ QCOMPARE(row->property("rightPadding").toDouble(), 1.0);
+ QTRY_COMPARE(row->width(), 114.0);
+ QCOMPARE(row->height(), 53.0);
+
+ obj->resetLeftPadding();
+ QCOMPARE(row->property("leftPadding").toDouble(), 1.0);
+ QTRY_COMPARE(row->width(), 112.0);
+ QCOMPARE(row->height(), 53.0);
+
+ obj->resetTopPadding();
+ QCOMPARE(row->property("topPadding").toDouble(), 1.0);
+ QTRY_COMPARE(row->height(), 52.0);
+ QCOMPARE(row->width(), 112.0);
+
+ obj->resetPadding();
+ QCOMPARE(row->property("padding").toDouble(), 0.0);
+ QCOMPARE(row->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(row->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(row->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(row->property("bottomPadding").toDouble(), 0.0);
+ QTRY_COMPARE(row->height(), 50.0);
+ QCOMPARE(row->width(), 110.0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
}
void tst_qquickpositioners::test_horizontal_rtl()
@@ -333,6 +543,36 @@ void tst_qquickpositioners::test_horizontal_rtl()
QCOMPARE(row->width(), 110.0);
QCOMPARE(row->height(), 50.0);
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->width(), 117.0);
+ QCOMPARE(row->height(), 57.0);
+
+ QCOMPARE(one->x(), 63.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 43.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 2.0);
+
+ row->setProperty("topPadding", 0);
+ row->setProperty("leftPadding", 0);
+ row->setProperty("rightPadding", 0);
+ row->setProperty("bottomPadding", 0);
+ row->setProperty("padding", 0);
+
+ QTRY_COMPARE(one->x(), 60.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 40.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 0.0);
+
// Change the width of the row and check that items stay to the right
row->setWidth(200);
QTRY_COMPARE(one->x(), 150.0);
@@ -342,6 +582,18 @@ void tst_qquickpositioners::test_horizontal_rtl()
QCOMPARE(three->x(), 90.0);
QCOMPARE(three->y(), 0.0);
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(one->x(), 146.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 126.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 86.0);
+ QCOMPARE(three->y(), 2.0);
}
void tst_qquickpositioners::test_horizontal_spacing()
@@ -370,6 +622,22 @@ void tst_qquickpositioners::test_horizontal_spacing()
QCOMPARE(row->width(), 130.0);
QCOMPARE(row->height(), 50.0);
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->width(), 137.0);
+ QCOMPARE(row->height(), 57.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 63.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 93.0);
+ QCOMPARE(three->y(), 2.0);
}
void tst_qquickpositioners::test_horizontal_spacing_rightToLeft()
@@ -391,13 +659,29 @@ void tst_qquickpositioners::test_horizontal_spacing_rightToLeft()
QCOMPARE(one->y(), 0.0);
QCOMPARE(two->x(), 50.0);
QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 00.0);
+ QCOMPARE(three->x(), 0.0);
QCOMPARE(three->y(), 0.0);
QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
QCOMPARE(row->width(), 130.0);
QCOMPARE(row->height(), 50.0);
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->width(), 137.0);
+ QCOMPARE(row->height(), 57.0);
+
+ QCOMPARE(one->x(), 83.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 2.0);
}
void tst_qquickpositioners::test_horizontal_animated()
@@ -453,6 +737,70 @@ void tst_qquickpositioners::test_horizontal_animated()
}
+void tst_qquickpositioners::test_horizontal_animated_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("horizontal-animated.qml"), false));
+
+ window->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ //Note that they animate in
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(three->x(), -100.0);
+
+ QVERIFY(QTest::qWaitForWindowExposed(window.data())); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
+ QVERIFY(row);
+ QCOMPARE(row->width(), 100.0);
+ QCOMPARE(row->height(), 50.0);
+
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->width(), 107.0);
+ QCOMPARE(row->height(), 57.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->x(), 3.0);
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(three->x(), 53.0);
+ QTRY_COMPARE(three->y(), 2.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QTRY_COMPARE(two->isVisible(), true);
+ QTRY_COMPARE(row->width(), 157.0);
+ QTRY_COMPARE(row->height(), 57.0);
+
+ QTest::qWait(0);//Let the animation start
+ QVERIFY(two->x() >= -100.0 && two->x() < 53.0);
+ QVERIFY(three->x() >= 53.0 && three->x() < 103.0);
+
+ QTRY_COMPARE(two->y(), 2.0);
+ QTRY_COMPARE(two->x(), 53.0);
+ QTRY_COMPARE(three->x(), 103.0);
+
+}
+
void tst_qquickpositioners::test_horizontal_animated_rightToLeft()
{
QScopedPointer<QQuickView> window(createView(testFile("horizontal-animated.qml"), false));
@@ -508,6 +856,72 @@ void tst_qquickpositioners::test_horizontal_animated_rightToLeft()
}
+void tst_qquickpositioners::test_horizontal_animated_rightToLeft_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("horizontal-animated.qml"), false));
+
+ window->rootObject()->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ //Note that they animate in
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(three->x(), -100.0);
+
+ QVERIFY(QTest::qWaitForWindowExposed(window.data())); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
+ QVERIFY(row);
+ QCOMPARE(row->width(), 100.0);
+ QCOMPARE(row->height(), 50.0);
+
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->width(), 107.0);
+ QCOMPARE(row->height(), 57.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->x(), 53.0);
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(three->x(), 3.0);
+ QTRY_COMPARE(three->y(), 2.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QTRY_COMPARE(two->isVisible(), true);
+
+ // New size should propagate after visible change
+ QTRY_COMPARE(row->width(), 157.0);
+ QTRY_COMPARE(row->height(), 57.0);
+
+ QTest::qWait(0);//Let the animation start
+ QVERIFY(one->x() >= 53.0 && one->x() < 100);
+ QVERIFY(two->x() >= -100.0 && two->x() < 53.0);
+
+ QTRY_COMPARE(one->x(), 103.0);
+ QTRY_COMPARE(two->y(), 2.0);
+ QTRY_COMPARE(two->x(), 53.0);
+
+}
+
void tst_qquickpositioners::test_horizontal_animated_disabled()
{
QScopedPointer<QQuickView> window(createView(testFile("horizontal-animated-disabled.qml")));
@@ -526,6 +940,54 @@ void tst_qquickpositioners::test_horizontal_animated_disabled()
qApp->processEvents();
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->width(), 107.0);
+ QCOMPARE(row->height(), 57.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->isVisible(), false);
+ QCOMPARE(two->x(), -100.0);//Not 'in' yet
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 53.0);
+ QCOMPARE(three->y(), 2.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QCOMPARE(two->isVisible(), true);
+ QTRY_COMPARE(row->width(), 157.0);
+ QTRY_COMPARE(row->height(), 57.0);
+
+ QTRY_COMPARE(two->y(), 2.0);
+ QTRY_COMPARE(two->x(), 53.0);
+ QTRY_COMPARE(three->x(), 103.0);
+
+}
+
+void tst_qquickpositioners::test_horizontal_animated_disabled_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("horizontal-animated-disabled.qml")));
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
+ QVERIFY(row);
+
+ qApp->processEvents();
+
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
QCOMPARE(two->isVisible(), false);
@@ -547,6 +1009,7 @@ void tst_qquickpositioners::test_horizontal_animated_disabled()
void tst_qquickpositioners::populateTransitions(const QString &positionerObjectName)
{
+ QFETCH(QString, qmlFile);
QFETCH(bool, dynamicallyPopulate);
QFETCH(bool, usePopulateTransition);
@@ -574,7 +1037,7 @@ void tst_qquickpositioners::populateTransitions(const QString &positionerObjectN
ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
ctxt->setContextProperty("testedPositioner", positionerObjectName);
- window->setSource(testFileUrl("transitions.qml"));
+ window->setSource(testFileUrl(qmlFile));
QQuickItem *positioner = window->rootObject()->findChild<QQuickItem*>(positionerObjectName);
QVERIFY(positioner);
@@ -619,18 +1082,24 @@ void tst_qquickpositioners::populateTransitions(const QString &positionerObjectN
void tst_qquickpositioners::populateTransitions_data()
{
+ QTest::addColumn<QString>("qmlFile");
QTest::addColumn<bool>("dynamicallyPopulate");
QTest::addColumn<bool>("usePopulateTransition");
- QTest::newRow("statically populate") << false << true;
- QTest::newRow("statically populate, no populate transition") << false << false;
+ QTest::newRow("statically populate") << "transitions.qml" << false << true;
+ QTest::newRow("statically populate, no populate transition") << "transitions.qml" << false << false;
+ QTest::newRow("padding, statically populate") << "transitions-padding.qml" << false << true;
+ QTest::newRow("padding, statically populate, no populate transition") << "transitions-padding.qml" << false << false;
- QTest::newRow("dynamically populate") << true << true;
- QTest::newRow("dynamically populate, no populate transition") << true << false;
+ QTest::newRow("dynamically populate") << "transitions.qml" << true << true;
+ QTest::newRow("dynamically populate, no populate transition") << "transitions.qml" << true << false;
+ QTest::newRow("padding, dynamically populate") << "transitions-padding.qml" << true << true;
+ QTest::newRow("padding, dynamically populate, no populate transition") << "transitions-padding.qml" << true << false;
}
void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
{
+ QFETCH(QString, qmlFile);
QFETCH(int, initialItemCount);
QFETCH(int, insertionIndex);
QFETCH(int, insertionCount);
@@ -654,7 +1123,7 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
ctxt->setContextProperty("testedPositioner", QString());
- window->setSource(testFileUrl("transitions.qml"));
+ window->setSource(testFileUrl(qmlFile));
window->show();
QTest::qWaitForWindowExposed(window.data());
qApp->processEvents();
@@ -729,22 +1198,30 @@ void tst_qquickpositioners::addTransitions_data()
{
// If this data changes, update addTransitions_grid_data() also
+ QTest::addColumn<QString>("qmlFile");
QTest::addColumn<int>("initialItemCount");
QTest::addColumn<int>("insertionIndex");
QTest::addColumn<int>("insertionCount");
QTest::addColumn<ListRange>("expectedDisplacedIndexes");
- QTest::newRow("add one @ start") << 10 << 0 << 1 << ListRange(0, 9);
- QTest::newRow("add one @ middle") << 10 << 5 << 1 << ListRange(5, 9);
- QTest::newRow("add one @ end") << 10 << 10 << 1 << ListRange();
+ QTest::newRow("add one @ start") << "transitions.qml" << 10 << 0 << 1 << ListRange(0, 9);
+ QTest::newRow("add one @ middle") << "transitions.qml" << 10 << 5 << 1 << ListRange(5, 9);
+ QTest::newRow("add one @ end") << "transitions.qml" << 10 << 10 << 1 << ListRange();
+ QTest::newRow("padding, add one @ start") << "transitions-padding.qml" << 10 << 0 << 1 << ListRange(0, 9);
+ QTest::newRow("padding, add one @ middle") << "transitions-padding.qml" << 10 << 5 << 1 << ListRange(5, 9);
+ QTest::newRow("padding, add one @ end") << "transitions-padding.qml" << 10 << 10 << 1 << ListRange();
- QTest::newRow("add multiple @ start") << 10 << 0 << 3 << ListRange(0, 9);
- QTest::newRow("add multiple @ middle") << 10 << 5 << 3 << ListRange(5, 9);
- QTest::newRow("add multiple @ end") << 10 << 10 << 3 << ListRange();
+ QTest::newRow("add multiple @ start") << "transitions.qml" << 10 << 0 << 3 << ListRange(0, 9);
+ QTest::newRow("add multiple @ middle") << "transitions.qml" << 10 << 5 << 3 << ListRange(5, 9);
+ QTest::newRow("add multiple @ end") << "transitions.qml" << 10 << 10 << 3 << ListRange();
+ QTest::newRow("padding, add multiple @ start") << "transitions-padding.qml" << 10 << 0 << 3 << ListRange(0, 9);
+ QTest::newRow("padding, add multiple @ middle") << "transitions-padding.qml" << 10 << 5 << 3 << ListRange(5, 9);
+ QTest::newRow("padding, add multiple @ end") << "transitions-padding.qml" << 10 << 10 << 3 << ListRange();
}
void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
{
+ QFETCH(QString, qmlFile);
QFETCH(int, initialItemCount);
QFETCH(ListChange, change);
QFETCH(ListRange, expectedDisplacedIndexes);
@@ -769,7 +1246,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
ctxt->setContextProperty("testedPositioner", QString());
- window->setSource(testFileUrl("transitions.qml"));
+ window->setSource(testFileUrl(qmlFile));
window->show();
QTest::qWaitForWindowExposed(window.data());
qApp->processEvents();
@@ -840,27 +1317,36 @@ void tst_qquickpositioners::moveTransitions_data()
{
// If this data changes, update moveTransitions_grid_data() also
+ QTest::addColumn<QString>("qmlFile");
QTest::addColumn<int>("initialItemCount");
QTest::addColumn<ListChange>("change");
QTest::addColumn<ListRange>("expectedDisplacedIndexes");
- QTest::newRow("remove one @ start") << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
- QTest::newRow("remove one @ middle") << 10 << ListChange::remove(4, 1) << ListRange(5, 9);
- QTest::newRow("remove one @ end") << 10 << ListChange::remove(9, 1) << ListRange();
+ QTest::newRow("remove one @ start") << "transitions.qml" << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
+ QTest::newRow("remove one @ middle") << "transitions.qml" << 10 << ListChange::remove(4, 1) << ListRange(5, 9);
+ QTest::newRow("remove one @ end") << "transitions.qml" << 10 << ListChange::remove(9, 1) << ListRange();
+ QTest::newRow("padding, remove one @ start") << "transitions-padding.qml" << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
+ QTest::newRow("padding, remove one @ middle") << "transitions-padding.qml" << 10 << ListChange::remove(4, 1) << ListRange(5, 9);
+ QTest::newRow("padding, remove one @ end") << "transitions-padding.qml" << 10 << ListChange::remove(9, 1) << ListRange();
- QTest::newRow("remove multiple @ start") << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
- QTest::newRow("remove multiple @ middle") << 10 << ListChange::remove(4, 3) << ListRange(7, 9);
- QTest::newRow("remove multiple @ end") << 10 << ListChange::remove(7, 3) << ListRange();
+ QTest::newRow("remove multiple @ start") << "transitions.qml" << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
+ QTest::newRow("remove multiple @ middle") << "transitions.qml" << 10 << ListChange::remove(4, 3) << ListRange(7, 9);
+ QTest::newRow("remove multiple @ end") << "transitions.qml" << 10 << ListChange::remove(7, 3) << ListRange();
+ QTest::newRow("padding, remove multiple @ start") << "transitions-padding.qml" << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
+ QTest::newRow("padding, remove multiple @ middle") << "transitions-padding.qml" << 10 << ListChange::remove(4, 3) << ListRange(7, 9);
+ QTest::newRow("padding, remove multiple @ end") << "transitions-padding.qml" << 10 << ListChange::remove(7, 3) << ListRange();
}
-
void tst_qquickpositioners::checkItemPositions(QQuickItem *positioner, QaimModel *model, qreal incrementalSize)
{
QVERIFY(model->count() > 0);
+
+ QQuickBasePositioner *p = qobject_cast<QQuickBasePositioner*>(positioner);
+
qreal padding = 0;
qreal currentSize = 30;
- qreal rowX = 0;
- qreal rowY = 0;
+ qreal rowX = p->leftPadding();
+ qreal rowY = p->topPadding();
for (int i=0; i<model->count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(positioner, "wrapper", i);
@@ -870,11 +1356,11 @@ void tst_qquickpositioners::checkItemPositions(QQuickItem *positioner, QaimModel
QCOMPARE(item->height(), currentSize);
if (qobject_cast<QQuickRow*>(positioner)) {
- QCOMPARE(item->x(), (i * 30.0) + padding);
- QCOMPARE(item->y(), 0.0);
+ QCOMPARE(item->x(), (i * 30.0) + padding + p->leftPadding());
+ QCOMPARE(item->y(), p->topPadding());
} else if (qobject_cast<QQuickColumn*>(positioner)) {
- QCOMPARE(item->x(), 0.0);
- QCOMPARE(item->y(), (i * 30.0) + padding);
+ QCOMPARE(item->x(), p->leftPadding());
+ QCOMPARE(item->y(), (i * 30.0) + padding + p->topPadding());
} else if (qobject_cast<QQuickGrid*>(positioner)) {
int columns = 4;
int rows = qCeil(model->count() / qreal(columns));
@@ -886,20 +1372,20 @@ void tst_qquickpositioners::checkItemPositions(QQuickItem *positioner, QaimModel
QVERIFY(finalAlignedRowItem);
QCOMPARE(item->x(), finalAlignedRowItem->x());
} else {
- QCOMPARE(item->x(), 0.0);
+ QCOMPARE(item->x(), p->leftPadding());
}
if (i / columns > 0) {
QQuickItem *prevRowLastItem = findItem<QQuickItem>(positioner, "wrapper", (i/columns * columns) - 1);
QVERIFY(prevRowLastItem);
QCOMPARE(item->y(), prevRowLastItem->y() + prevRowLastItem->height());
} else {
- QCOMPARE(item->y(), 0.0);
+ QCOMPARE(item->y(), p->topPadding());
}
} else if (qobject_cast<QQuickFlow*>(positioner)) {
if (rowX + item->width() > positioner->width()) {
QQuickItem *prevItem = findItem<QQuickItem>(positioner, "wrapper", i-1);
QVERIFY(prevItem);
- rowX = 0;
+ rowX = p->leftPadding();
rowY = prevItem->y() + prevItem->height();
}
QCOMPARE(item->x(), rowX);
@@ -942,6 +1428,183 @@ void tst_qquickpositioners::test_vertical()
QCOMPARE(column->height(), 80.0);
QCOMPARE(column->width(), 50.0);
+ // test padding
+ column->setProperty("padding", 1);
+ column->setProperty("topPadding", 2);
+ column->setProperty("leftPadding", 3);
+ column->setProperty("rightPadding", 4);
+ column->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(column->height(), 87.0);
+ QCOMPARE(column->width(), 57.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 3.0);
+ QCOMPARE(two->y(), 52.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 62.0);
+}
+
+void tst_qquickpositioners::test_vertical_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("vertical.qml")));
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 60.0);
+
+ QQuickItem *column = window->rootObject()->findChild<QQuickItem*>("column");
+ QVERIFY(column);
+ QCOMPARE(column->height(), 80.0);
+ QCOMPARE(column->width(), 50.0);
+
+ QQuickColumn *obj = qobject_cast<QQuickColumn*>(column);
+ QVERIFY(obj != 0);
+
+ QCOMPARE(column->property("padding").toDouble(), 0.0);
+ QCOMPARE(column->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(column->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(column->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(column->property("bottomPadding").toDouble(), 0.0);
+
+ obj->setPadding(1.0);
+
+ QCOMPARE(column->property("padding").toDouble(), 1.0);
+ QCOMPARE(column->property("topPadding").toDouble(), 1.0);
+ QCOMPARE(column->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(column->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(column->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(column->height(), 82.0);
+ QCOMPARE(column->width(), 52.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 1.0);
+ QCOMPARE(two->x(), 1.0);
+ QCOMPARE(two->y(), 51.0);
+ QCOMPARE(three->x(), 1.0);
+ QCOMPARE(three->y(), 61.0);
+
+ obj->setTopPadding(2.0);
+
+ QCOMPARE(column->property("padding").toDouble(), 1.0);
+ QCOMPARE(column->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(column->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(column->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(column->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(column->height(), 83.0);
+ QCOMPARE(column->width(), 52.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 1.0);
+ QCOMPARE(two->y(), 52.0);
+ QCOMPARE(three->x(), 1.0);
+ QCOMPARE(three->y(), 62.0);
+
+ obj->setLeftPadding(3.0);
+
+ QCOMPARE(column->property("padding").toDouble(), 1.0);
+ QCOMPARE(column->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(column->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(column->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(column->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(column->width(), 54.0);
+ QCOMPARE(column->height(), 83.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 3.0);
+ QCOMPARE(two->y(), 52.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 62.0);
+
+ obj->setRightPadding(4.0);
+
+ QCOMPARE(column->property("padding").toDouble(), 1.0);
+ QCOMPARE(column->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(column->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(column->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(column->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(column->width(), 57.0);
+ QCOMPARE(column->height(), 83.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 3.0);
+ QCOMPARE(two->y(), 52.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 62.0);
+
+ obj->setBottomPadding(5.0);
+
+ QCOMPARE(column->property("padding").toDouble(), 1.0);
+ QCOMPARE(column->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(column->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(column->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(column->property("bottomPadding").toDouble(), 5.0);
+
+ QTRY_COMPARE(column->height(), 87.0);
+ QCOMPARE(column->width(), 57.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 3.0);
+ QCOMPARE(two->y(), 52.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 62.0);
+
+ obj->resetBottomPadding();
+ QCOMPARE(column->property("bottomPadding").toDouble(), 1.0);
+ QTRY_COMPARE(column->height(), 83.0);
+ QCOMPARE(column->width(), 57.0);
+
+ obj->resetRightPadding();
+ QCOMPARE(column->property("rightPadding").toDouble(), 1.0);
+ QTRY_COMPARE(column->width(), 54.0);
+ QCOMPARE(column->height(), 83.0);
+
+ obj->resetLeftPadding();
+ QCOMPARE(column->property("leftPadding").toDouble(), 1.0);
+ QTRY_COMPARE(column->width(), 52.0);
+ QCOMPARE(column->height(), 83.0);
+
+ obj->resetTopPadding();
+ QCOMPARE(column->property("topPadding").toDouble(), 1.0);
+ QTRY_COMPARE(column->height(), 82.0);
+ QCOMPARE(column->width(), 52.0);
+
+ obj->resetPadding();
+ QCOMPARE(column->property("padding").toDouble(), 0.0);
+ QCOMPARE(column->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(column->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(column->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(column->property("bottomPadding").toDouble(), 0.0);
+ QTRY_COMPARE(column->height(), 80.0);
+ QCOMPARE(column->width(), 50.0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 60.0);
}
void tst_qquickpositioners::test_vertical_spacing()
@@ -968,6 +1631,22 @@ void tst_qquickpositioners::test_vertical_spacing()
QCOMPARE(column->height(), 100.0);
QCOMPARE(column->width(), 50.0);
+ // test padding
+ column->setProperty("padding", 1);
+ column->setProperty("topPadding", 2);
+ column->setProperty("leftPadding", 3);
+ column->setProperty("rightPadding", 4);
+ column->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(column->height(), 107.0);
+ QCOMPARE(column->width(), 57.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 3.0);
+ QCOMPARE(two->y(), 62.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 82.0);
}
void tst_qquickpositioners::test_vertical_animated()
@@ -1019,6 +1698,66 @@ void tst_qquickpositioners::test_vertical_animated()
}
+void tst_qquickpositioners::test_vertical_animated_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("vertical-animated.qml"), false));
+
+ //Note that they animate in
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->y(), -100.0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->y(), -100.0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->y(), -100.0);
+
+ QVERIFY(QTest::qWaitForWindowExposed(window.data())); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *column = window->rootObject()->findChild<QQuickItem*>("column");
+ QVERIFY(column);
+ QCOMPARE(column->height(), 100.0);
+ QCOMPARE(column->width(), 50.0);
+
+ // test padding
+ column->setProperty("padding", 1);
+ column->setProperty("topPadding", 2);
+ column->setProperty("leftPadding", 3);
+ column->setProperty("rightPadding", 4);
+ column->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(column->height(), 107.0);
+ QCOMPARE(column->width(), 57.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(one->x(), 3.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->y(), -100.0);//Not 'in' yet
+ QTRY_COMPARE(two->x(), 0.0);
+ QTRY_COMPARE(three->y(), 52.0);
+ QTRY_COMPARE(three->x(), 3.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QTRY_COMPARE(two->isVisible(), true);
+ QTRY_COMPARE(column->height(), 157.0);
+ QTRY_COMPARE(column->width(), 57.0);
+ QTest::qWait(0);//Let the animation start
+ QVERIFY(two->y() >= -100.0 && two->y() < 52.0);
+ QVERIFY(three->y() >= 52.0 && three->y() < 102.0);
+
+ QTRY_COMPARE(two->x(), 3.0);
+ QTRY_COMPARE(two->y(), 52.0);
+ QTRY_COMPARE(three->y(), 102.0);
+
+}
+
void tst_qquickpositioners::test_grid()
{
QScopedPointer<QQuickView> window(createView(testFile("gridtest.qml")));
@@ -1050,6 +1789,214 @@ void tst_qquickpositioners::test_grid()
QCOMPARE(grid->width(), 100.0);
QCOMPARE(grid->height(), 100.0);
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 52.0);
+}
+
+void tst_qquickpositioners::test_grid_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("gridtest.qml")));
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickGrid *grid = window->rootObject()->findChild<QQuickGrid*>("grid");
+ QCOMPARE(grid->flow(), QQuickGrid::LeftToRight);
+ QCOMPARE(grid->width(), 100.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ QCOMPARE(grid->property("padding").toDouble(), 0.0);
+ QCOMPARE(grid->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(grid->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(grid->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 0.0);
+
+ grid->setPadding(1.0);
+
+ QCOMPARE(grid->property("padding").toDouble(), 1.0);
+ QCOMPARE(grid->property("topPadding").toDouble(), 1.0);
+ QCOMPARE(grid->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(grid->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(grid->width(), 102.0);
+ QCOMPARE(grid->height(), 102.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 1.0);
+ QCOMPARE(two->x(), 51.0);
+ QCOMPARE(two->y(), 1.0);
+ QCOMPARE(three->x(), 71.0);
+ QCOMPARE(three->y(), 1.0);
+ QCOMPARE(four->x(), 1.0);
+ QCOMPARE(four->y(), 51.0);
+ QCOMPARE(five->x(), 51.0);
+ QCOMPARE(five->y(), 51.0);
+
+ grid->setTopPadding(2.0);
+
+ QCOMPARE(grid->property("padding").toDouble(), 1.0);
+ QCOMPARE(grid->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(grid->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(grid->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(grid->height(), 103.0);
+ QCOMPARE(grid->width(), 102.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 51.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 71.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 1.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 51.0);
+ QCOMPARE(five->y(), 52.0);
+
+ grid->setLeftPadding(3.0);
+
+ QCOMPARE(grid->property("padding").toDouble(), 1.0);
+ QCOMPARE(grid->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(grid->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(grid->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(grid->width(), 104.0);
+ QCOMPARE(grid->height(), 103.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 52.0);
+
+ grid->setRightPadding(4.0);
+
+ QCOMPARE(grid->property("padding").toDouble(), 1.0);
+ QCOMPARE(grid->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(grid->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(grid->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 103.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 52.0);
+
+ grid->setBottomPadding(5.0);
+
+ QCOMPARE(grid->property("padding").toDouble(), 1.0);
+ QCOMPARE(grid->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(grid->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(grid->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 5.0);
+
+ QTRY_COMPARE(grid->height(), 107.0);
+ QCOMPARE(grid->width(), 107.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 52.0);
+
+ grid->resetBottomPadding();
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 1.0);
+ QTRY_COMPARE(grid->height(), 103.0);
+ QCOMPARE(grid->width(), 107.0);
+
+ grid->resetRightPadding();
+ QCOMPARE(grid->property("rightPadding").toDouble(), 1.0);
+ QTRY_COMPARE(grid->width(), 104.0);
+ QCOMPARE(grid->height(), 103.0);
+
+ grid->resetLeftPadding();
+ QCOMPARE(grid->property("leftPadding").toDouble(), 1.0);
+ QTRY_COMPARE(grid->width(), 102.0);
+ QCOMPARE(grid->height(), 103.0);
+
+ grid->resetTopPadding();
+ QCOMPARE(grid->property("topPadding").toDouble(), 1.0);
+ QTRY_COMPARE(grid->height(), 102.0);
+ QCOMPARE(grid->width(), 102.0);
+
+ grid->resetPadding();
+ QCOMPARE(grid->property("padding").toDouble(), 0.0);
+ QCOMPARE(grid->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(grid->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(grid->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(grid->property("bottomPadding").toDouble(), 0.0);
+ QTRY_COMPARE(grid->height(), 100.0);
+ QCOMPARE(grid->width(), 100.0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
}
void tst_qquickpositioners::test_grid_topToBottom()
@@ -1083,6 +2030,26 @@ void tst_qquickpositioners::test_grid_topToBottom()
QCOMPARE(grid->width(), 100.0);
QCOMPARE(grid->height(), 120.0);
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 127.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 3.0);
+ QCOMPARE(two->y(), 52.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 102.0);
+ QCOMPARE(four->x(), 53.0);
+ QCOMPARE(four->y(), 2.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 52.0);
}
void tst_qquickpositioners::test_grid_rightToLeft()
@@ -1118,6 +2085,44 @@ void tst_qquickpositioners::test_grid_rightToLeft()
QCOMPARE(grid->width(), 100.0);
QCOMPARE(grid->height(), 100.0);
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ QCOMPARE(one->x(), 53.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 33.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 53.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 43.0);
+ QCOMPARE(five->y(), 52.0);
+
+ grid->setProperty("topPadding", 0);
+ grid->setProperty("leftPadding", 0);
+ grid->setProperty("rightPadding", 0);
+ grid->setProperty("bottomPadding", 0);
+ grid->setProperty("padding", 0);
+
+ QTRY_COMPARE(one->x(), 50.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 30.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 50.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 40.0);
+ QCOMPARE(five->y(), 50.0);
+
// Change the width of the grid and check that items stay to the right
grid->setWidth(200);
QTRY_COMPARE(one->x(), 150.0);
@@ -1131,6 +2136,22 @@ void tst_qquickpositioners::test_grid_rightToLeft()
QCOMPARE(five->x(), 140.0);
QCOMPARE(five->y(), 50.0);
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(one->x(), 146.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 126.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 96.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 146.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 136.0);
+ QCOMPARE(five->y(), 52.0);
}
void tst_qquickpositioners::test_grid_spacing()
@@ -1163,6 +2184,26 @@ void tst_qquickpositioners::test_grid_spacing()
QCOMPARE(grid->width(), 128.0);
QCOMPARE(grid->height(), 104.0);
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 135.0);
+ QCOMPARE(grid->height(), 111.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 57.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 81.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 56.0);
+ QCOMPARE(five->x(), 57.0);
+ QCOMPARE(five->y(), 56.0);
}
void tst_qquickpositioners::test_grid_row_column_spacing()
@@ -1195,6 +2236,26 @@ void tst_qquickpositioners::test_grid_row_column_spacing()
QCOMPARE(grid->width(), 142.0);
QCOMPARE(grid->height(), 107.0);
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 149.0);
+ QCOMPARE(grid->height(), 114.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 64.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 95.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 59.0);
+ QCOMPARE(five->x(), 64.0);
+ QCOMPARE(five->y(), 59.0);
}
void tst_qquickpositioners::test_grid_animated()
@@ -1281,6 +2342,100 @@ void tst_qquickpositioners::test_grid_animated()
}
+void tst_qquickpositioners::test_grid_animated_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("grid-animated.qml"), false));
+
+ window->rootObject()->setProperty("testRightToLeft", false);
+
+ //Note that all animate in
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(one->y(), -100.0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->x(), -100.0);
+ QCOMPARE(three->y(), -100.0);
+
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QCOMPARE(four->x(), -100.0);
+ QCOMPARE(four->y(), -100.0);
+
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+ QCOMPARE(five->x(), -100.0);
+ QCOMPARE(five->y(), -100.0);
+
+ QVERIFY(QTest::qWaitForWindowExposed(window.data())); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *grid = window->rootObject()->findChild<QQuickItem*>("grid");
+ QVERIFY(grid);
+ QCOMPARE(grid->width(), 150.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 157.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(one->x(), 3.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->y(), -100.0);
+ QTRY_COMPARE(two->x(), -100.0);
+ QTRY_COMPARE(three->y(), 2.0);
+ QTRY_COMPARE(three->x(), 53.0);
+ QTRY_COMPARE(four->y(), 2.0);
+ QTRY_COMPARE(four->x(), 103.0);
+ QTRY_COMPARE(five->y(), 52.0);
+ QTRY_COMPARE(five->x(), 3.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QCOMPARE(two->isVisible(), true);
+ QCOMPARE(grid->width(), 157.0);
+ QCOMPARE(grid->height(), 107.0);
+ QTest::qWait(0);//Let the animation start
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(three->x(), 53.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 103.0);
+ QCOMPARE(four->y(), 2.0);
+ QCOMPARE(five->x(), 3.0);
+ QCOMPARE(five->y(), 52.0);
+ //Let the animation complete
+ QTRY_COMPARE(two->x(), 53.0);
+ QTRY_COMPARE(two->y(), 2.0);
+ QTRY_COMPARE(one->x(), 3.0);
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(three->x(), 103.0);
+ QTRY_COMPARE(three->y(), 2.0);
+ QTRY_COMPARE(four->x(), 3.0);
+ QTRY_COMPARE(four->y(), 52.0);
+ QTRY_COMPARE(five->x(), 53.0);
+ QTRY_COMPARE(five->y(), 52.0);
+
+}
+
void tst_qquickpositioners::test_grid_animated_rightToLeft()
{
QScopedPointer<QQuickView> window(createView(testFile("grid-animated.qml"), false));
@@ -1365,6 +2520,100 @@ void tst_qquickpositioners::test_grid_animated_rightToLeft()
}
+void tst_qquickpositioners::test_grid_animated_rightToLeft_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("grid-animated.qml"), false));
+
+ window->rootObject()->setProperty("testRightToLeft", true);
+
+ //Note that all animate in
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(one->y(), -100.0);
+
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->x(), -100.0);
+ QCOMPARE(three->y(), -100.0);
+
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QCOMPARE(four->x(), -100.0);
+ QCOMPARE(four->y(), -100.0);
+
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+ QCOMPARE(five->x(), -100.0);
+ QCOMPARE(five->y(), -100.0);
+
+ QVERIFY(QTest::qWaitForWindowExposed(window.data())); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *grid = window->rootObject()->findChild<QQuickItem*>("grid");
+ QVERIFY(grid);
+ QCOMPARE(grid->width(), 150.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 157.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(one->x(), 103.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->y(), -100.0);
+ QTRY_COMPARE(two->x(), -100.0);
+ QTRY_COMPARE(three->y(), 2.0);
+ QTRY_COMPARE(three->x(), 53.0);
+ QTRY_COMPARE(four->y(), 2.0);
+ QTRY_COMPARE(four->x(), 3.0);
+ QTRY_COMPARE(five->y(), 52.0);
+ QTRY_COMPARE(five->x(), 103.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QCOMPARE(two->isVisible(), true);
+ QCOMPARE(grid->width(), 157.0);
+ QCOMPARE(grid->height(), 107.0);
+ QTest::qWait(0);//Let the animation start
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+ QCOMPARE(one->x(), 103.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(three->x(), 53.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 2.0);
+ QCOMPARE(five->x(), 103.0);
+ QCOMPARE(five->y(), 52.0);
+ //Let the animation complete
+ QTRY_COMPARE(two->x(), 53.0);
+ QTRY_COMPARE(two->y(), 2.0);
+ QTRY_COMPARE(one->x(), 103.0);
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(three->x(), 3.0);
+ QTRY_COMPARE(three->y(), 2.0);
+ QTRY_COMPARE(four->x(), 103.0);
+ QTRY_COMPARE(four->y(), 52.0);
+ QTRY_COMPARE(five->x(), 53.0);
+ QTRY_COMPARE(five->y(), 52.0);
+
+}
+
void tst_qquickpositioners::test_grid_zero_columns()
{
QScopedPointer<QQuickView> window(createView(testFile("gridzerocolumns.qml")));
@@ -1395,6 +2644,26 @@ void tst_qquickpositioners::test_grid_zero_columns()
QCOMPARE(grid->width(), 170.0);
QCOMPARE(grid->height(), 60.0);
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 177.0);
+ QCOMPARE(grid->height(), 67.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 123.0);
+ QCOMPARE(four->y(), 2.0);
+ QCOMPARE(five->x(), 3.0);
+ QCOMPARE(five->y(), 52.0);
}
void tst_qquickpositioners::test_grid_H_alignment()
@@ -1476,6 +2745,95 @@ void tst_qquickpositioners::test_grid_H_alignment()
}
+void tst_qquickpositioners::test_grid_H_alignment_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("gridtest.qml")));
+
+ window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignHCenter);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 55.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickItem *grid = window->rootObject()->findChild<QQuickItem*>("grid");
+ QCOMPARE(grid->width(), 100.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignRight);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 63.0);
+ QCOMPARE(five->y(), 52.0);
+ QCOMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ window->rootObject()->setProperty("testRightToLeft", true);
+
+ QCOMPARE(one->x(), 53.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 33.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 53.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 33.0);
+ QCOMPARE(five->y(), 52.0);
+ QCOMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignHCenter);
+
+ QCOMPARE(one->x(), 53.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 33.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 2.0);
+ QCOMPARE(four->x(), 53.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 38.0);
+ QCOMPARE(five->y(), 52.0);
+ QCOMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 107.0);
+
+}
+
void tst_qquickpositioners::test_grid_V_alignment()
{
QScopedPointer<QQuickView> window(createView(testFile("gridtest.qml")));
@@ -1519,6 +2877,63 @@ void tst_qquickpositioners::test_grid_V_alignment()
}
+void tst_qquickpositioners::test_grid_V_alignment_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("gridtest.qml")));
+
+ window->rootObject()->setProperty("testVAlignment", QQuickGrid::AlignVCenter);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QQuickItem *grid = window->rootObject()->findChild<QQuickItem*>("grid");
+ QCOMPARE(grid->width(), 100.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->width(), 107.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 17.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 72.0);
+
+ window->rootObject()->setProperty("testVAlignment", QQuickGrid::AlignBottom);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 73.0);
+ QCOMPARE(three->y(), 32.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 92.0);
+
+}
+
void tst_qquickpositioners::test_propertychanges()
{
QScopedPointer<QQuickView> window(createView(testFile("propertychangestest.qml")));
@@ -1599,6 +3014,28 @@ void tst_qquickpositioners::test_repeater()
}
+void tst_qquickpositioners::test_repeater_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("repeatertest-padding.qml")));
+
+ QQuickRectangle *one = findItem<QQuickRectangle>(window->contentItem(), "one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = findItem<QQuickRectangle>(window->contentItem(), "two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = findItem<QQuickRectangle>(window->contentItem(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 103.0);
+ QCOMPARE(three->y(), 2.0);
+
+}
+
void tst_qquickpositioners::test_flow()
{
QScopedPointer<QQuickView> window(createView(testFile("flowtest.qml")));
@@ -1632,6 +3069,219 @@ void tst_qquickpositioners::test_flow()
QCOMPARE(flow->width(), 90.0);
QCOMPARE(flow->height(), 120.0);
+ // test padding
+ flow->setProperty("padding", 1);
+ flow->setProperty("topPadding", 2);
+ flow->setProperty("leftPadding", 3);
+ flow->setProperty("rightPadding", 4);
+ flow->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(flow->height(), 127.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 72.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 72.0);
+}
+
+void tst_qquickpositioners::test_flow_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("flowtest.qml")));
+
+ window->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 70.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 70.0);
+
+ QQuickItem *flow = window->rootObject()->findChild<QQuickItem*>("flow");
+ QVERIFY(flow);
+ QCOMPARE(flow->width(), 90.0);
+ QCOMPARE(flow->height(), 120.0);
+
+ QQuickFlow *obj = qobject_cast<QQuickFlow*>(flow);
+ QVERIFY(obj != 0);
+
+ QCOMPARE(flow->property("padding").toDouble(), 0.0);
+ QCOMPARE(flow->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(flow->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(flow->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 0.0);
+
+ obj->setPadding(1.0);
+
+ QCOMPARE(flow->property("padding").toDouble(), 1.0);
+ QCOMPARE(flow->property("topPadding").toDouble(), 1.0);
+ QCOMPARE(flow->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(flow->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(flow->height(), 122.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 1.0);
+ QCOMPARE(two->x(), 51.0);
+ QCOMPARE(two->y(), 1.0);
+ QCOMPARE(three->x(), 1.0);
+ QCOMPARE(three->y(), 51.0);
+ QCOMPARE(four->x(), 1.0);
+ QCOMPARE(four->y(), 71.0);
+ QCOMPARE(five->x(), 51.0);
+ QCOMPARE(five->y(), 71.0);
+
+ obj->setTopPadding(2.0);
+
+ QCOMPARE(flow->property("padding").toDouble(), 1.0);
+ QCOMPARE(flow->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(flow->property("leftPadding").toDouble(), 1.0);
+ QCOMPARE(flow->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 1.0);
+
+ QTRY_COMPARE(flow->height(), 123.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QCOMPARE(one->x(), 1.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 51.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 1.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 1.0);
+ QCOMPARE(four->y(), 72.0);
+ QCOMPARE(five->x(), 51.0);
+ QCOMPARE(five->y(), 72.0);
+
+ obj->setLeftPadding(3.0);
+
+ QCOMPARE(flow->property("padding").toDouble(), 1.0);
+ QCOMPARE(flow->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(flow->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(flow->property("rightPadding").toDouble(), 1.0);
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 1.0);
+
+ QCOMPARE(flow->height(), 123.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QTRY_COMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 72.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 72.0);
+
+ obj->setRightPadding(4.0);
+
+ QCOMPARE(flow->property("padding").toDouble(), 1.0);
+ QCOMPARE(flow->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(flow->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(flow->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 1.0);
+
+ QCOMPARE(flow->height(), 123.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QTRY_COMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 72.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 72.0);
+
+ obj->setBottomPadding(5.0);
+
+ QCOMPARE(flow->property("padding").toDouble(), 1.0);
+ QCOMPARE(flow->property("topPadding").toDouble(), 2.0);
+ QCOMPARE(flow->property("leftPadding").toDouble(), 3.0);
+ QCOMPARE(flow->property("rightPadding").toDouble(), 4.0);
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 5.0);
+
+ QTRY_COMPARE(flow->height(), 127.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 3.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 72.0);
+ QCOMPARE(five->x(), 53.0);
+ QCOMPARE(five->y(), 72.0);
+
+ obj->resetBottomPadding();
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 1.0);
+ QTRY_COMPARE(flow->height(), 123.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ obj->resetRightPadding();
+ QCOMPARE(flow->property("rightPadding").toDouble(), 1.0);
+ QTRY_COMPARE(flow->height(), 123.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ obj->resetLeftPadding();
+ QCOMPARE(flow->property("leftPadding").toDouble(), 1.0);
+ QTRY_COMPARE(flow->height(), 123.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ obj->resetTopPadding();
+ QCOMPARE(flow->property("topPadding").toDouble(), 1.0);
+ QTRY_COMPARE(flow->height(), 122.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ obj->resetPadding();
+ QCOMPARE(flow->property("padding").toDouble(), 0.0);
+ QCOMPARE(flow->property("topPadding").toDouble(), 0.0);
+ QCOMPARE(flow->property("leftPadding").toDouble(), 0.0);
+ QCOMPARE(flow->property("rightPadding").toDouble(), 0.0);
+ QCOMPARE(flow->property("bottomPadding").toDouble(), 0.0);
+ QTRY_COMPARE(flow->height(), 120.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 70.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 70.0);
}
void tst_qquickpositioners::test_flow_rightToLeft()
@@ -1667,6 +3317,26 @@ void tst_qquickpositioners::test_flow_rightToLeft()
QCOMPARE(flow->width(), 90.0);
QCOMPARE(flow->height(), 120.0);
+ // test padding
+ flow->setProperty("padding", 1);
+ flow->setProperty("topPadding", 2);
+ flow->setProperty("leftPadding", 3);
+ flow->setProperty("rightPadding", 4);
+ flow->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(flow->height(), 127.0);
+ QCOMPARE(flow->width(), 90.0);
+
+ QCOMPARE(one->x(), 36.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 16.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 36.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 36.0);
+ QCOMPARE(four->y(), 72.0);
+ QCOMPARE(five->x(), 26.0);
+ QCOMPARE(five->y(), 72.0);
}
void tst_qquickpositioners::test_flow_topToBottom()
@@ -1693,7 +3363,7 @@ void tst_qquickpositioners::test_flow_topToBottom()
QCOMPARE(three->x(), 50.0);
QCOMPARE(three->y(), 50.0);
QCOMPARE(four->x(), 100.0);
- QCOMPARE(four->y(), 00.0);
+ QCOMPARE(four->y(), 0.0);
QCOMPARE(five->x(), 100.0);
QCOMPARE(five->y(), 50.0);
@@ -1721,6 +3391,79 @@ void tst_qquickpositioners::test_flow_topToBottom()
}
+void tst_qquickpositioners::test_flow_topToBottom_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("flowtest-toptobottom.qml")));
+
+ window->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(four->x(), 100.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(five->x(), 100.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickItem *flow = window->rootObject()->findChild<QQuickItem*>("flow");
+ QVERIFY(flow);
+ QCOMPARE(flow->height(), 90.0);
+ QCOMPARE(flow->width(), 150.0);
+
+ // test padding
+ flow->setProperty("padding", 1);
+ flow->setProperty("topPadding", 2);
+ flow->setProperty("leftPadding", 3);
+ flow->setProperty("rightPadding", 4);
+ flow->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(flow->width(), 157.0);
+ QCOMPARE(flow->height(), 90.0);
+
+ QCOMPARE(one->x(), 3.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 53.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 53.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 103.0);
+ QCOMPARE(four->y(), 2.0);
+ QCOMPARE(five->x(), 103.0);
+ QCOMPARE(five->y(), 52.0);
+
+ window->rootObject()->setProperty("testRightToLeft", true);
+
+ QVERIFY(flow);
+ QTRY_COMPARE(flow->width(), 157.0);
+ QCOMPARE(flow->height(), 90.0);
+
+ QCOMPARE(one->x(), 103.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 83.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 53.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 3.0);
+ QCOMPARE(four->y(), 2.0);
+ QCOMPARE(five->x(), 43.0);
+ QCOMPARE(five->y(), 52.0);
+
+}
+
void tst_qquickpositioners::test_flow_resize()
{
QScopedPointer<QQuickView> window(createView(testFile("flowtest.qml")));
@@ -1754,6 +3497,39 @@ void tst_qquickpositioners::test_flow_resize()
}
+void tst_qquickpositioners::test_flow_resize_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("flowtest-padding.qml")));
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root);
+ root->setWidth(125);
+ root->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QTRY_COMPARE(one->x(), 3.0);
+ QTRY_COMPARE(one->y(), 2.0);
+ QTRY_COMPARE(two->x(), 53.0);
+ QTRY_COMPARE(two->y(), 2.0);
+ QTRY_COMPARE(three->x(), 3.0);
+ QTRY_COMPARE(three->y(), 52.0);
+ QTRY_COMPARE(four->x(), 53.0);
+ QTRY_COMPARE(four->y(), 52.0);
+ QTRY_COMPARE(five->x(), 103.0);
+ QTRY_COMPARE(five->y(), 52.0);
+
+}
+
void tst_qquickpositioners::test_flow_resize_rightToLeft()
{
QScopedPointer<QQuickView> window(createView(testFile("flowtest.qml")));
@@ -1787,6 +3563,39 @@ void tst_qquickpositioners::test_flow_resize_rightToLeft()
}
+void tst_qquickpositioners::test_flow_resize_rightToLeft_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("flowtest-padding.qml")));
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root);
+ root->setWidth(125);
+ root->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
+ QTRY_VERIFY(one != 0);
+ QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 71.0);
+ QCOMPARE(one->y(), 2.0);
+ QCOMPARE(two->x(), 51.0);
+ QCOMPARE(two->y(), 2.0);
+ QCOMPARE(three->x(), 71.0);
+ QCOMPARE(three->y(), 52.0);
+ QCOMPARE(four->x(), 21.0);
+ QCOMPARE(four->y(), 52.0);
+ QCOMPARE(five->x(), 11.0);
+ QCOMPARE(five->y(), 52.0);
+
+}
+
void tst_qquickpositioners::test_flow_implicit_resize()
{
QScopedPointer<QQuickView> window(createView(testFile("flow-testimplicitsize.qml")));
@@ -1815,6 +3624,44 @@ void tst_qquickpositioners::test_flow_implicit_resize()
}
+void tst_qquickpositioners::test_flow_implicit_resize_padding()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("flow-testimplicitsize.qml")));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickFlow *flow = window->rootObject()->findChild<QQuickFlow*>("flow");
+ QVERIFY(flow != 0);
+
+ QCOMPARE(flow->width(), 100.0);
+ QCOMPARE(flow->height(), 120.0);
+
+ // test padding
+ flow->setProperty("padding", 1);
+ flow->setProperty("topPadding", 2);
+ flow->setProperty("leftPadding", 3);
+ flow->setProperty("rightPadding", 4);
+ flow->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(flow->width(), 107.0);
+ QCOMPARE(flow->height(), 127.0);
+
+ window->rootObject()->setProperty("flowLayout", 0);
+ QCOMPARE(flow->flow(), QQuickFlow::LeftToRight);
+ QCOMPARE(flow->width(), 227.0);
+ QCOMPARE(flow->height(), 57.0);
+
+ window->rootObject()->setProperty("flowLayout", 1);
+ QCOMPARE(flow->flow(), QQuickFlow::TopToBottom);
+ QCOMPARE(flow->width(), 107.0);
+ QCOMPARE(flow->height(), 127.0);
+
+ window->rootObject()->setProperty("flowLayout", 2);
+ QCOMPARE(flow->layoutDirection(), Qt::RightToLeft);
+ QCOMPARE(flow->width(), 227.0);
+ QCOMPARE(flow->height(), 57.0);
+
+}
+
void tst_qquickpositioners::test_conflictinganchors()
{
QQmlTestMessageHandler messageHandler;
@@ -1924,7 +3771,9 @@ void tst_qquickpositioners::test_conflictinganchors()
void tst_qquickpositioners::test_mirroring()
{
QList<QString> qmlFiles;
- qmlFiles << "horizontal.qml" << "gridtest.qml" << "flowtest.qml";
+ qmlFiles << "horizontal.qml" << "horizontal-padding.qml"
+ << "gridtest.qml" << "gridtest-padding.qml"
+ << "flowtest.qml" << "flowtest-padding.qml";
QList<QString> objectNames;
objectNames << "one" << "two" << "three" << "four" << "five";
@@ -1942,8 +3791,8 @@ void tst_qquickpositioners::test_mirroring()
// LTR != RTL
foreach (const QString objectName, objectNames) {
- // horizontal.qml only has three items
- if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+ // horizontal.qml and horizontal-padding.qml only have three items
+ if (qmlFile.startsWith(QString("horizontal")) && objectName == QString("four"))
break;
QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
@@ -1957,8 +3806,8 @@ void tst_qquickpositioners::test_mirroring()
// RTL == mirror
foreach (const QString objectName, objectNames) {
- // horizontal.qml only has three items
- if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+ // horizontal.qml and horizontal-padding.qml only have three items
+ if (qmlFile.startsWith(QString("horizontal")) && objectName == QString("four"))
break;
QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
@@ -1978,8 +3827,8 @@ void tst_qquickpositioners::test_mirroring()
// LTR == RTL + mirror
foreach (const QString objectName, objectNames) {
- // horizontal.qml only has three items
- if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+ // horizontal.qml and horizontal-padding.qml only have three items
+ if (qmlFile.startsWith(QString("horizontal")) && objectName == QString("four"))
break;
QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
@@ -2000,10 +3849,61 @@ void tst_qquickpositioners::test_allInvisible()
QVERIFY(row != 0);
QVERIFY(row->width() == 0);
QVERIFY(row->height() == 0);
+
+ // test padding
+ row->setProperty("padding", 1);
+ row->setProperty("topPadding", 2);
+ row->setProperty("leftPadding", 3);
+ row->setProperty("rightPadding", 4);
+ row->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(row->height(), 7.0);
+ QCOMPARE(row->width(), 7.0);
+
QQuickColumn *column = window->rootObject()->findChild<QQuickColumn*>("column");
QVERIFY(column != 0);
QVERIFY(column->width() == 0);
QVERIFY(column->height() == 0);
+
+ // test padding
+ column->setProperty("padding", 1);
+ column->setProperty("topPadding", 2);
+ column->setProperty("leftPadding", 3);
+ column->setProperty("rightPadding", 4);
+ column->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(column->height(), 7.0);
+ QCOMPARE(column->width(), 7.0);
+
+ QQuickGrid *grid = window->rootObject()->findChild<QQuickGrid*>("grid");
+ QVERIFY(grid != 0);
+ QVERIFY(grid->width() == 0);
+ QVERIFY(grid->height() == 0);
+
+ // test padding
+ grid->setProperty("padding", 1);
+ grid->setProperty("topPadding", 2);
+ grid->setProperty("leftPadding", 3);
+ grid->setProperty("rightPadding", 4);
+ grid->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(grid->height(), 7.0);
+ QCOMPARE(grid->width(), 7.0);
+
+ QQuickFlow *flow = window->rootObject()->findChild<QQuickFlow*>("flow");
+ QVERIFY(flow != 0);
+ QVERIFY(flow->width() == 0);
+ QVERIFY(flow->height() == 0);
+
+ // test padding
+ flow->setProperty("padding", 1);
+ flow->setProperty("topPadding", 2);
+ flow->setProperty("leftPadding", 3);
+ flow->setProperty("rightPadding", 4);
+ flow->setProperty("bottomPadding", 5);
+
+ QTRY_COMPARE(flow->height(), 7.0);
+ QCOMPARE(flow->width(), 7.0);
}
void tst_qquickpositioners::test_attachedproperties()
diff --git a/tests/auto/quick/qquickrepeater/data/objectmodel.qml b/tests/auto/quick/qquickrepeater/data/objectmodel.qml
new file mode 100644
index 0000000000..780f53e802
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/objectmodel.qml
@@ -0,0 +1,28 @@
+import QtQuick 2.0
+import QtQml.Models 2.1
+
+Row {
+ width: 360
+ height: 360
+
+ Repeater {
+ objectName: "repeater"
+ model: ObjectModel {
+ Rectangle {
+ width: 20
+ height: 20
+ color: "red"
+ }
+ Rectangle {
+ width: 20
+ height: 20
+ color: "green"
+ }
+ Rectangle {
+ width: 20
+ height: 20
+ color: "blue"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/data/stackingorder.qml b/tests/auto/quick/qquickrepeater/data/stackingorder.qml
new file mode 100644
index 0000000000..41dadca0df
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/stackingorder.qml
@@ -0,0 +1,38 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+ property bool stackingOrderOk: true
+
+ function verifyStackingOrder() {
+ var len = children.length
+ for (var i = 0; i < len; ++i) {
+ var expectedName;
+ if (i === 0) {
+ expectedName = "first"
+ } else if (i === len - 2) {
+ expectedName = "repeater"
+ } else if (i === len - 1) {
+ expectedName = "last"
+ } else {
+ expectedName = "middle" + (i - 1)
+ }
+ if (children[i].objectName !== expectedName)
+ stackingOrderOk = false
+ }
+ }
+ Item {
+ objectName: "first"
+ }
+ Repeater {
+ objectName: "repeater"
+ model: 1
+ Item {
+ objectName: "middle" + index
+ Component.onCompleted: { verifyStackingOrder();}
+ }
+ }
+ Item {
+ objectName: "last"
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index b2039bd323..3d0bb8f1ed 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -41,6 +41,7 @@
#include <private/qquickrepeater_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmllistmodel_p.h>
+#include <QtQml/private/qqmlobjectmodel_p.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
@@ -76,6 +77,8 @@ private slots:
void jsArrayChange();
void clearRemovalOrder();
void destroyCount();
+ void stackingOrder();
+ void objectModel();
};
class TestObject : public QObject
@@ -894,6 +897,82 @@ void tst_QQuickRepeater::destroyCount()
QCOMPARE(repeater->property("componentCount").toInt(), 4);
}
+void tst_QQuickRepeater::stackingOrder()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("stackingorder.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(rootObject);
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
+ QVERIFY(repeater);
+ int count = 1;
+ do {
+ bool stackingOrderOk = rootObject->property("stackingOrderOk").toBool();
+ QVERIFY(stackingOrderOk);
+ repeater->setModel(QVariant(++count));
+ } while (count < 3);
+}
+
+static bool compareObjectModel(QQuickRepeater *repeater, QQmlObjectModel *model)
+{
+ if (repeater->count() != model->count())
+ return false;
+ for (int i = 0; i < repeater->count(); ++i) {
+ if (repeater->itemAt(i) != model->get(i))
+ return false;
+ }
+ return true;
+}
+
+void tst_QQuickRepeater::objectModel()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("objectmodel.qml"));
+
+ QQuickItem *positioner = qobject_cast<QQuickItem *>(component.create());
+ QVERIFY(positioner);
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(positioner, "repeater");
+ QVERIFY(repeater);
+
+ QQmlObjectModel *model = repeater->model().value<QQmlObjectModel *>();
+ QVERIFY(model);
+
+ QVERIFY(repeater->itemAt(0));
+ QVERIFY(repeater->itemAt(1));
+ QVERIFY(repeater->itemAt(2));
+ QCOMPARE(repeater->itemAt(0)->property("color").toString(), QColor("red").name());
+ QCOMPARE(repeater->itemAt(1)->property("color").toString(), QColor("green").name());
+ QCOMPARE(repeater->itemAt(2)->property("color").toString(), QColor("blue").name());
+
+ QQuickItem *item0 = new QQuickItem(positioner);
+ item0->setSize(QSizeF(20, 20));
+ model->append(item0);
+ QCOMPARE(model->count(), 4);
+ QVERIFY(compareObjectModel(repeater, model));
+
+ QQuickItem *item1 = new QQuickItem(positioner);
+ item1->setSize(QSizeF(20, 20));
+ model->insert(0, item1);
+ QCOMPARE(model->count(), 5);
+ QVERIFY(compareObjectModel(repeater, model));
+
+ model->move(1, 2, 3);
+ QVERIFY(compareObjectModel(repeater, model));
+
+ model->remove(2, 2);
+ QCOMPARE(model->count(), 3);
+ QVERIFY(compareObjectModel(repeater, model));
+
+ model->clear();
+ QCOMPARE(model->count(), 0);
+ QCOMPARE(repeater->count(), 0);
+
+ delete positioner;
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 6c42a7a0ee..4748cd2514 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -1637,7 +1637,7 @@ void tst_qquickstates::QTBUG_38492()
void tst_qquickstates::revertListMemoryLeak()
{
- QWeakPointer<QQmlAbstractBinding> weakPtr;
+ QQmlAbstractBinding::Ptr bindingPtr;
{
QQmlEngine engine;
@@ -1651,12 +1651,12 @@ void tst_qquickstates::revertListMemoryLeak()
QQmlAbstractBinding *binding = state->bindingInRevertList(item, "height");
QVERIFY(binding);
- weakPtr = QQmlAbstractBinding::getPointer(binding);
- QVERIFY(!weakPtr.toStrongRef().isNull());
+ bindingPtr = binding;
+ QVERIFY(bindingPtr->ref > 1);
delete item;
}
- QVERIFY(weakPtr.toStrongRef().isNull());
+ QVERIFY(bindingPtr->ref == 1);
}
QTEST_MAIN(tst_qquickstates)
diff --git a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
index b76218edb9..3c05d4ac73 100644
--- a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
+++ b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
@@ -169,7 +169,7 @@ void tst_qquickstyledtext::textOutput()
QCOMPARE(layout.text(), output);
- QList<QTextLayout::FormatRange> layoutFormats = layout.additionalFormats();
+ const QVector<QTextLayout::FormatRange> layoutFormats = layout.formats();
QCOMPARE(layoutFormats.count(), formats.count());
for (int i = 0; i < formats.count(); ++i) {
@@ -198,7 +198,7 @@ void tst_qquickstyledtext::anchors()
QCOMPARE(layout.text(), output);
- QList<QTextLayout::FormatRange> layoutFormats = layout.additionalFormats();
+ const QVector<QTextLayout::FormatRange> layoutFormats = layout.formats();
QCOMPARE(layoutFormats.count(), formats.count());
for (int i = 0; i < formats.count(); ++i) {
diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST
new file mode 100644
index 0000000000..0c65f1e245
--- /dev/null
+++ b/tests/auto/quick/qquicktext/BLACKLIST
@@ -0,0 +1,4 @@
+[dependentImplicitSizes]
+*
+[mouseSelection]
+*
diff --git a/tests/auto/quick/qquicktext/data/padding.qml b/tests/auto/quick/qquicktext/data/padding.qml
new file mode 100644
index 0000000000..ab0a37d041
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/padding.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.6
+
+Text {
+ width: 200; height: 200
+ text: "Hello Qt"
+
+ padding: 10
+ topPadding: 20
+ leftPadding: 30
+ rightPadding: 40
+ bottomPadding: 50
+}
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index eb9f7529fe..c1d454e5df 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -148,6 +148,8 @@ private slots:
void growFromZeroWidth();
+ void padding();
+
private:
QStringList standard;
QStringList richText;
@@ -2048,7 +2050,7 @@ void tst_qquicktext::embeddedImages_data()
QTest::newRow("remote") << testFileUrl("embeddedImagesRemote.qml") << "";
QTest::newRow("remote-error") << testFileUrl("embeddedImagesRemoteError.qml")
<< testFileUrl("embeddedImagesRemoteError.qml").toString()+":3:1: QML Text: Error downloading {{ServerBaseUrl}}/notexists.png - server replied: Not found";
- QTest::newRow("remote") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
+ QTest::newRow("remote-relative") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
}
void tst_qquicktext::embeddedImages()
@@ -2058,6 +2060,14 @@ void tst_qquicktext::embeddedImages()
QFETCH(QUrl, qmlfile);
QFETCH(QString, error);
+#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
+ if (qstrcmp(QTest::currentDataTag(), "remote") == 0
+ || qstrcmp(QTest::currentDataTag(), "remote-error") == 0
+ || qstrcmp(QTest::currentDataTag(), "remote-relative") == 0) {
+ QSKIP("Remote tests cause occasional hangs in the CI system -- QTBUG-45655");
+ }
+#endif
+
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
server.serveDirectory(testFile("http"));
@@ -3634,19 +3644,19 @@ Q_DECLARE_METATYPE(ExpectedBaseline)
static qreal expectedBaselineTop(QQuickText *item)
{
QFontMetricsF fm(item->font());
- return fm.ascent();
+ return fm.ascent() + item->topPadding();
}
static qreal expectedBaselineBottom(QQuickText *item)
{
QFontMetricsF fm(item->font());
- return item->height() - item->contentHeight() + fm.ascent();
+ return item->height() - item->contentHeight() - item->bottomPadding() + fm.ascent();
}
static qreal expectedBaselineCenter(QQuickText *item)
{
QFontMetricsF fm(item->font());
- return ((item->height() - item->contentHeight()) / 2) + fm.ascent();
+ return ((item->height() - item->contentHeight() - item->topPadding() - item->bottomPadding()) / 2) + fm.ascent() + item->topPadding();
}
static qreal expectedBaselineBold(QQuickText *item)
@@ -3654,7 +3664,7 @@ static qreal expectedBaselineBold(QQuickText *item)
QFont font = item->font();
font.setBold(true);
QFontMetricsF fm(font);
- return fm.ascent();
+ return fm.ascent() + item->topPadding();
}
static qreal expectedBaselineImage(QQuickText *item)
@@ -3664,13 +3674,13 @@ static qreal expectedBaselineImage(QQuickText *item)
// or image height - line height and the baseline is line position + ascent. Because
// QTextLine's height is rounded up this can give slightly different results to image height
// - descent.
- return 181 - qCeil(fm.height()) + fm.ascent();
+ return 181 - qCeil(fm.height()) + fm.ascent() + item->topPadding();
}
static qreal expectedBaselineCustom(QQuickText *item)
{
QFontMetricsF fm(item->font());
- return 16 + fm.ascent();
+ return 16 + fm.ascent() + item->topPadding();
}
static qreal expectedBaselineScaled(QQuickText *item)
@@ -3689,11 +3699,11 @@ static qreal expectedBaselineScaled(QQuickText *item)
if (width < item->width()) {
QFontMetricsF fm(layout.font());
- return fm.ascent();
+ return fm.ascent() + item->topPadding();
}
font.setPointSize(font.pointSize() - 1);
} while (font.pointSize() > 0);
- return 0;
+ return item->topPadding();
}
static qreal expectedBaselineFixedBottom(QQuickText *item)
@@ -3702,7 +3712,7 @@ static qreal expectedBaselineFixedBottom(QQuickText *item)
qreal dy = item->text().contains(QLatin1Char('\n'))
? 160
: 180;
- return dy + fm.ascent();
+ return dy + fm.ascent() - item->bottomPadding();
}
static qreal expectedBaselineProportionalBottom(QQuickText *item)
@@ -3711,7 +3721,7 @@ static qreal expectedBaselineProportionalBottom(QQuickText *item)
qreal dy = item->text().contains(QLatin1Char('\n'))
? 200 - (qCeil(fm.height()) * 3)
: 200 - (qCeil(fm.height()) * 1.5);
- return dy + fm.ascent();
+ return dy + fm.ascent() - item->bottomPadding();
}
void tst_qquicktext::baselineOffset_data()
@@ -3818,6 +3828,102 @@ void tst_qquicktext::baselineOffset_data()
<< QByteArray("height: 200; lineHeightMode: Text.ProportionalHeight; lineHeight: 1.5; verticalAlignment: Text.AlignBottom")
<< &expectedBaselineProportionalBottom
<< &expectedBaselineProportionalBottom;
+
+ QTest::newRow("top align with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; verticalAlignment: Text.AlignTop")
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+ QTest::newRow("bottom align with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; verticalAlignment: Text.AlignBottom")
+ << &expectedBaselineBottom
+ << &expectedBaselineBottom;
+ QTest::newRow("center align with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; verticalAlignment: Text.AlignVCenter")
+ << &expectedBaselineCenter
+ << &expectedBaselineCenter;
+
+ QTest::newRow("bold width padding")
+ << "<b>hello world</b>"
+ << "<b>hello<br/>world</b>"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20")
+ << &expectedBaselineTop
+ << &expectedBaselineBold;
+
+ QTest::newRow("richText with padding")
+ << "<b>hello world</b>"
+ << "<b>hello<br/>world</b>"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; textFormat: Text.RichText")
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("elided with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("width: 20; height: 8; topPadding: 10; bottomPadding: 20; elide: Text.ElideRight")
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("elided bottom align with padding")
+ << "hello world"
+ << "hello\nworld!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+ << QByteArray("width: 200; height: 200; topPadding: 10; bottomPadding: 20; elide: Text.ElideRight; verticalAlignment: Text.AlignBottom")
+ << &expectedBaselineBottom
+ << &expectedBaselineBottom;
+
+ QTest::newRow("image with padding")
+ << "hello <img src=\"images/heart200.png\" /> world"
+ << "hello <img src=\"images/heart200.png\" /><br/>world"
+ << QByteArray("height: 200\n; topPadding: 10; bottomPadding: 20; baseUrl: \"") + testFileUrl("reference").toEncoded() + QByteArray("\"")
+ << &expectedBaselineImage
+ << &expectedBaselineTop;
+
+ QTest::newRow("customLine with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; onLineLaidOut: line.y += 16")
+ << &expectedBaselineCustom
+ << &expectedBaselineCustom;
+
+ QTest::newRow("scaled font with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("width: 200; topPadding: 10; bottomPadding: 20; minimumPointSize: 1; font.pointSize: 64; fontSizeMode: Text.HorizontalFit")
+ << &expectedBaselineScaled
+ << &expectedBaselineTop;
+
+ QTest::newRow("fixed line height top align with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; lineHeightMode: Text.FixedHeight; lineHeight: 20; verticalAlignment: Text.AlignTop")
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("fixed line height bottom align with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; lineHeightMode: Text.FixedHeight; lineHeight: 20; verticalAlignment: Text.AlignBottom")
+ << &expectedBaselineFixedBottom
+ << &expectedBaselineFixedBottom;
+
+ QTest::newRow("proportional line height top align with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; lineHeightMode: Text.ProportionalHeight; lineHeight: 1.5; verticalAlignment: Text.AlignTop")
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("proportional line height bottom align with padding")
+ << "hello world"
+ << "hello\nworld"
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; lineHeightMode: Text.ProportionalHeight; lineHeight: 1.5; verticalAlignment: Text.AlignBottom")
+ << &expectedBaselineProportionalBottom
+ << &expectedBaselineProportionalBottom;
}
void tst_qquicktext::baselineOffset()
@@ -3830,7 +3936,7 @@ void tst_qquicktext::baselineOffset()
QQmlComponent component(&engine);
component.setData(
- "import QtQuick 2.0\n"
+ "import QtQuick 2.6\n"
"Text {\n"
+ bindings + "\n"
"}", QUrl());
@@ -3972,6 +4078,84 @@ void tst_qquicktext::growFromZeroWidth()
QVERIFY(text->lineCount() > 3);
}
+void tst_qquicktext::padding()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("padding.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QQuickItem *root = window->rootObject();
+ QVERIFY(root);
+ QQuickText *obj = qobject_cast<QQuickText*>(root);
+ QVERIFY(obj != 0);
+
+ qreal cw = obj->contentWidth();
+ qreal ch = obj->contentHeight();
+
+ QVERIFY(cw > 0);
+ QVERIFY(ch > 0);
+
+ QCOMPARE(obj->topPadding(), 20.0);
+ QCOMPARE(obj->leftPadding(), 30.0);
+ QCOMPARE(obj->rightPadding(), 40.0);
+ QCOMPARE(obj->bottomPadding(), 50.0);
+
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setTopPadding(2.25);
+ QCOMPARE(obj->topPadding(), 2.25);
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setLeftPadding(3.75);
+ QCOMPARE(obj->leftPadding(), 3.75);
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+
+ obj->setRightPadding(4.4);
+ QCOMPARE(obj->rightPadding(), 4.4);
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+
+ obj->setBottomPadding(1.11);
+ QCOMPARE(obj->bottomPadding(), 1.11);
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setText("Qt");
+ QVERIFY(obj->contentWidth() < cw);
+ QCOMPARE(obj->contentHeight(), ch);
+ cw = obj->contentWidth();
+
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setFont(QFont("Courier", 96));
+ QVERIFY(obj->contentWidth() > cw);
+ QVERIFY(obj->contentHeight() > ch);
+ cw = obj->contentWidth();
+ ch = obj->contentHeight();
+
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->resetTopPadding();
+ QCOMPARE(obj->topPadding(), 10.0);
+ obj->resetLeftPadding();
+ QCOMPARE(obj->leftPadding(), 10.0);
+ obj->resetRightPadding();
+ QCOMPARE(obj->rightPadding(), 10.0);
+ obj->resetBottomPadding();
+ QCOMPARE(obj->bottomPadding(), 10.0);
+
+ obj->resetPadding();
+ QCOMPARE(obj->padding(), 0.0);
+ QCOMPARE(obj->topPadding(), 0.0);
+ QCOMPARE(obj->leftPadding(), 0.0);
+ QCOMPARE(obj->rightPadding(), 0.0);
+ QCOMPARE(obj->bottomPadding(), 0.0);
+
+ delete root;
+}
+
QTEST_MAIN(tst_qquicktext)
#include "tst_qquicktext.moc"
diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST
new file mode 100644
index 0000000000..492d81531a
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/BLACKLIST
@@ -0,0 +1,2 @@
+[mouseSelection]
+*
diff --git a/tests/auto/quick/qquicktextedit/data/padding.qml b/tests/auto/quick/qquicktextedit/data/padding.qml
new file mode 100644
index 0000000000..f4852bec8b
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/padding.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.6
+
+TextEdit {
+ width: 200; height: 200
+ text: "Hello Qt"
+
+ padding: 10
+ topPadding: 20
+ leftPadding: 30
+ rightPadding: 40
+ bottomPadding: 50
+}
diff --git a/tests/auto/quick/qquicktextedit/data/signal_editingfinished.qml b/tests/auto/quick/qquicktextedit/data/signal_editingfinished.qml
new file mode 100644
index 0000000000..b5caab5e7c
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/signal_editingfinished.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.6
+
+Item {
+ property QtObject input1: input1
+ property QtObject input2: input2
+
+ width: 800; height: 600
+
+ Column{
+ TextEdit { id: input1; activeFocusOnTab: true }
+ TextEdit { id: input2; activeFocusOnTab: true }
+ }
+}
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 9d1d099c0e..e5c4d0aba5 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -166,6 +166,8 @@ private slots:
void implicitSizeBinding_data();
void implicitSizeBinding();
+ void signal_editingfinished();
+
void preeditCursorRectangle();
void inputMethodComposing();
void cursorRectangleSize_data();
@@ -200,6 +202,8 @@ private slots:
void cursorRectangle_QTBUG_38947();
void textCached_QTBUG_41583();
+ void padding();
+
private:
void simulateKeys(QWindow *window, const QList<Key> &keys);
void simulateKeys(QWindow *window, const QKeySequence &sequence);
@@ -3316,6 +3320,53 @@ void tst_qquicktextedit::implicitSizeBinding()
QCOMPARE(textObject->height(), textObject->implicitHeight());
}
+void tst_qquicktextedit::signal_editingfinished()
+{
+ QQuickView *window = new QQuickView(0);
+ window->setBaseSize(QSize(800,600));
+
+ window->setSource(testFileUrl("signal_editingfinished.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(QGuiApplication::focusWindow() == window);
+
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickTextEdit *input1 = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window->rootObject()->property("input1")));
+ QVERIFY(input1);
+ QQuickTextEdit *input2 = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window->rootObject()->property("input2")));
+ QVERIFY(input2);
+
+ QSignalSpy editingFinished1Spy(input1, SIGNAL(editingFinished()));
+
+ input1->setFocus(true);
+ QTRY_VERIFY(input1->hasActiveFocus());
+ QTRY_VERIFY(!input2->hasActiveFocus());
+
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QTRY_COMPARE(editingFinished1Spy.count(), 1);
+
+ QTRY_VERIFY(!input1->hasActiveFocus());
+ QTRY_VERIFY(input2->hasActiveFocus());
+
+ QSignalSpy editingFinished2Spy(input2, SIGNAL(editingFinished()));
+
+ input2->setFocus(true);
+ QTRY_VERIFY(!input1->hasActiveFocus());
+ QTRY_VERIFY(input2->hasActiveFocus());
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QTRY_COMPARE(editingFinished2Spy.count(), 1);
+
+ QTRY_VERIFY(input1->hasActiveFocus());
+ QTRY_VERIFY(!input2->hasActiveFocus());
+}
+
void tst_qquicktextedit::clipRect()
{
QQmlComponent component(&engine);
@@ -5323,6 +5374,84 @@ void tst_qquicktextedit::textCached_QTBUG_41583()
QVERIFY(!textedit->property("empty").toBool());
}
+void tst_qquicktextedit::padding()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("padding.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QQuickItem *root = window->rootObject();
+ QVERIFY(root);
+ QQuickTextEdit *obj = qobject_cast<QQuickTextEdit*>(root);
+ QVERIFY(obj != 0);
+
+ qreal cw = obj->contentWidth();
+ qreal ch = obj->contentHeight();
+
+ QVERIFY(cw > 0);
+ QVERIFY(ch > 0);
+
+ QCOMPARE(obj->topPadding(), 20.0);
+ QCOMPARE(obj->leftPadding(), 30.0);
+ QCOMPARE(obj->rightPadding(), 40.0);
+ QCOMPARE(obj->bottomPadding(), 50.0);
+
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setTopPadding(2.25);
+ QCOMPARE(obj->topPadding(), 2.25);
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setLeftPadding(3.75);
+ QCOMPARE(obj->leftPadding(), 3.75);
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+
+ obj->setRightPadding(4.4);
+ QCOMPARE(obj->rightPadding(), 4.4);
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+
+ obj->setBottomPadding(1.11);
+ QCOMPARE(obj->bottomPadding(), 1.11);
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setText("Qt");
+ QVERIFY(obj->contentWidth() < cw);
+ QCOMPARE(obj->contentHeight(), ch);
+ cw = obj->contentWidth();
+
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->setFont(QFont("Courier", 96));
+ QVERIFY(obj->contentWidth() > cw);
+ QVERIFY(obj->contentHeight() > ch);
+ cw = obj->contentWidth();
+ ch = obj->contentHeight();
+
+ QCOMPARE(obj->implicitWidth(), cw + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), ch + obj->topPadding() + obj->bottomPadding());
+
+ obj->resetTopPadding();
+ QCOMPARE(obj->topPadding(), 10.0);
+ obj->resetLeftPadding();
+ QCOMPARE(obj->leftPadding(), 10.0);
+ obj->resetRightPadding();
+ QCOMPARE(obj->rightPadding(), 10.0);
+ obj->resetBottomPadding();
+ QCOMPARE(obj->bottomPadding(), 10.0);
+
+ obj->resetPadding();
+ QCOMPARE(obj->padding(), 0.0);
+ QCOMPARE(obj->topPadding(), 0.0);
+ QCOMPARE(obj->leftPadding(), 0.0);
+ QCOMPARE(obj->rightPadding(), 0.0);
+ QCOMPARE(obj->bottomPadding(), 0.0);
+
+ delete root;
+}
+
QTEST_MAIN(tst_qquicktextedit)
#include "tst_qquicktextedit.moc"
diff --git a/tests/auto/quick/qquicktextinput/data/padding.qml b/tests/auto/quick/qquicktextinput/data/padding.qml
new file mode 100644
index 0000000000..23bfe20f22
--- /dev/null
+++ b/tests/auto/quick/qquicktextinput/data/padding.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.6
+
+TextInput {
+ width: 200; height: 200
+ text: "Hello Qt"
+
+ padding: 10
+ topPadding: 20
+ leftPadding: 30
+ rightPadding: 40
+ bottomPadding: 50
+}
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 88cac92864..9ded3870c7 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -45,6 +45,7 @@
#include <QInputMethod>
#include <private/qquicktextinput_p.h>
#include <private/qquicktextinput_p_p.h>
+#include <private/qquickvalidator_p.h>
#include <QDebug>
#include <QDir>
#include <math.h>
@@ -222,6 +223,7 @@ private slots:
void baselineOffset();
void ensureVisible();
+ void padding();
private:
void simulateKey(QWindow *, int key);
@@ -2996,6 +2998,14 @@ void tst_qquicktextinput::cursorRectangle_data()
<< false;
}
+#ifndef QT_NO_IM
+#define COMPARE_INPUT_METHOD_QUERY(type, input, property, method, result) \
+ QCOMPARE((type) input->inputMethodQuery(property).method(), result);
+#else
+#define COMPARE_INPUT_METHOD_QUERY(type, input, property, method, result) \
+ qt_noop()
+#endif
+
void tst_qquicktextinput::cursorRectangle()
{
QFETCH(QString, text);
@@ -3035,7 +3045,7 @@ void tst_qquicktextinput::cursorRectangle()
r = input.cursorRectangle();
QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3045,7 +3055,7 @@ void tst_qquicktextinput::cursorRectangle()
for (int i = positionAtWidth + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
QCOMPARE(r, input.cursorRectangle());
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3058,7 +3068,7 @@ void tst_qquicktextinput::cursorRectangle()
} else {
QVERIFY(r.left() <= input.width());
}
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3071,7 +3081,7 @@ void tst_qquicktextinput::cursorRectangle()
QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(r.top(), 0.);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3083,14 +3093,14 @@ void tst_qquicktextinput::cursorRectangle()
QCOMPARE(r.left(), input.width());
}
QVERIFY(r.top() >= line.height() - 1);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(11), r);
for (int i = wrapPosition + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
QVERIFY(r.top() >= line.height() - 1);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3102,7 +3112,7 @@ void tst_qquicktextinput::cursorRectangle()
QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(r.top(), 0.);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3112,7 +3122,7 @@ void tst_qquicktextinput::cursorRectangle()
for (int i = positionAtWidth + 1; i < wrapPosition && leftToRight; ++i) {
input.setCursorPosition(i);
QCOMPARE(r, input.cursorRectangle());
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3124,14 +3134,14 @@ void tst_qquicktextinput::cursorRectangle()
QCOMPARE(r.left(), input.width());
}
QVERIFY(r.bottom() >= input.height());
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(11), r);
for (int i = wrapPosition + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
QVERIFY(r.bottom() >= input.height());
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3139,7 +3149,7 @@ void tst_qquicktextinput::cursorRectangle()
input.setCursorPosition(i);
r = input.cursorRectangle();
QVERIFY(r.bottom() >= input.height());
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3147,13 +3157,13 @@ void tst_qquicktextinput::cursorRectangle()
r = input.cursorRectangle();
QCOMPARE(r.top(), 0.);
QCOMPARE(r.left(), leftToRight ? input.width() : 0);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(10), r);
for (int i = wrapPosition - 2; i >= positionAtWidth + 1; --i) {
input.setCursorPosition(i);
QCOMPARE(r, input.cursorRectangle());
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3161,7 +3171,7 @@ void tst_qquicktextinput::cursorRectangle()
input.setCursorPosition(i);
r = input.cursorRectangle();
QCOMPARE(r.top(), 0.);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -3230,7 +3240,7 @@ void tst_qquicktextinput::echoMode()
//Normal
ref &= ~Qt::ImhHiddenText;
ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
- QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
+ COMPARE_INPUT_METHOD_QUERY(Qt::InputMethodHints, input, Qt::ImHints, toInt, ref);
input->setEchoMode(QQuickTextInput::NoEcho);
QCOMPARE(input->text(), initial);
QCOMPARE(input->displayText(), QLatin1String(""));
@@ -3238,17 +3248,17 @@ void tst_qquicktextinput::echoMode()
//NoEcho
ref |= Qt::ImhHiddenText;
ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
- QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
+ COMPARE_INPUT_METHOD_QUERY(Qt::InputMethodHints, input, Qt::ImHints, toInt, ref);
input->setEchoMode(QQuickTextInput::Password);
//Password
ref |= Qt::ImhHiddenText;
ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
QCOMPARE(input->text(), initial);
QCOMPARE(input->displayText(), QString(8, passwordMaskCharacter.at(0)));
- QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
+ COMPARE_INPUT_METHOD_QUERY(Qt::InputMethodHints, input, Qt::ImHints, toInt, ref);
// clearing input hints do not clear bits set by echo mode
input->setInputMethodHints(Qt::ImhNone);
- QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
+ COMPARE_INPUT_METHOD_QUERY(Qt::InputMethodHints, input, Qt::ImHints, toInt, ref);
input->setPasswordCharacter(QChar('Q'));
QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
QCOMPARE(input->text(), initial);
@@ -3257,19 +3267,20 @@ void tst_qquicktextinput::echoMode()
//PasswordEchoOnEdit
ref &= ~Qt::ImhHiddenText;
ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
- QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
+ COMPARE_INPUT_METHOD_QUERY(Qt::InputMethodHints, input, Qt::ImHints, toInt, ref);
QCOMPARE(input->text(), initial);
QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
+ COMPARE_INPUT_METHOD_QUERY(QString, input, Qt::ImSurroundingText, toString,
+ QLatin1String("QQQQQQQQ"));
QTest::keyPress(&window, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10);
QCOMPARE(input->text(), QLatin1String("a"));
QCOMPARE(input->displayText(), QLatin1String("a"));
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
+ COMPARE_INPUT_METHOD_QUERY(QString, input, Qt::ImSurroundingText, toString, QLatin1String("a"));
input->setFocus(false);
QVERIFY(input->hasActiveFocus() == false);
QCOMPARE(input->displayText(), QLatin1String("Q"));
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
+ COMPARE_INPUT_METHOD_QUERY(QString, input, Qt::ImSurroundingText, toString, QLatin1String("Q"));
input->setFocus(true);
QVERIFY(input->hasActiveFocus());
QInputMethodEvent inputEvent;
@@ -3277,7 +3288,7 @@ void tst_qquicktextinput::echoMode()
QGuiApplication::sendEvent(input, &inputEvent);
QCOMPARE(input->text(), initial);
QCOMPARE(input->displayText(), initial);
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
+ COMPARE_INPUT_METHOD_QUERY(QString, input, Qt::ImSurroundingText, toString, initial);
}
void tst_qquicktextinput::passwordEchoDelay()
@@ -6370,25 +6381,25 @@ Q_DECLARE_METATYPE(ExpectedBaseline)
static qreal expectedBaselineTop(QQuickTextInput *item)
{
QFontMetricsF fm(item->font());
- return fm.ascent();
+ return fm.ascent() + item->topPadding();
}
static qreal expectedBaselineBottom(QQuickTextInput *item)
{
QFontMetricsF fm(item->font());
- return item->height() - item->contentHeight() + fm.ascent();
+ return item->height() - item->contentHeight() - item->bottomPadding() + fm.ascent();
}
static qreal expectedBaselineCenter(QQuickTextInput *item)
{
QFontMetricsF fm(item->font());
- return ((item->height() - item->contentHeight()) / 2) + fm.ascent();
+ return ((item->height() - item->contentHeight() - item->topPadding() - item->bottomPadding()) / 2) + fm.ascent() + item->topPadding();
}
static qreal expectedBaselineMultilineBottom(QQuickTextInput *item)
{
QFontMetricsF fm(item->font());
- return item->height() - item->contentHeight() + fm.ascent();
+ return item->height() - item->contentHeight() - item->bottomPadding() + fm.ascent();
}
void tst_qquicktextinput::baselineOffset_data()
@@ -6433,6 +6444,41 @@ void tst_qquicktextinput::baselineOffset_data()
<< -1.
<< &expectedBaselineMultilineBottom
<< &expectedBaselineBottom;
+
+ QTest::newRow("padding")
+ << "Typography"
+ << QByteArray("topPadding: 10; bottomPadding: 20")
+ << -1.
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("top align with padding")
+ << "Typography"
+ << QByteArray("height: 200; verticalAlignment: Text.AlignTop; topPadding: 10; bottomPadding: 20")
+ << -1.
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("bottom align with padding")
+ << "Typography"
+ << QByteArray("height: 200; verticalAlignment: Text.AlignBottom; topPadding: 10; bottomPadding: 20")
+ << 100.
+ << &expectedBaselineBottom
+ << &expectedBaselineBottom;
+
+ QTest::newRow("center align with padding")
+ << "Typography"
+ << QByteArray("height: 200; verticalAlignment: Text.AlignVCenter; topPadding: 10; bottomPadding: 20")
+ << 100.
+ << &expectedBaselineCenter
+ << &expectedBaselineCenter;
+
+ QTest::newRow("multiline bottom aligned with padding")
+ << "The quick brown fox jumps over the lazy dog"
+ << QByteArray("height: 200; width: 30; verticalAlignment: Text.AlignBottom; wrapMode: TextInput.WordWrap; topPadding: 10; bottomPadding: 20")
+ << -1.
+ << &expectedBaselineMultilineBottom
+ << &expectedBaselineBottom;
}
void tst_qquicktextinput::baselineOffset()
@@ -6445,7 +6491,7 @@ void tst_qquicktextinput::baselineOffset()
QQmlComponent component(&engine);
component.setData(
- "import QtQuick 2.0\n"
+ "import QtQuick 2.6\n"
"TextInput {\n"
+ bindings + "\n"
"}", QUrl());
@@ -6510,6 +6556,85 @@ void tst_qquicktextinput::ensureVisible()
QCOMPARE(input->boundingRect().height(), line.height());
}
+void tst_qquicktextinput::padding()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("padding.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QQuickItem *root = window->rootObject();
+ QVERIFY(root);
+ QQuickTextInput *obj = qobject_cast<QQuickTextInput*>(root);
+ QVERIFY(obj != 0);
+
+ qreal cw = obj->contentWidth();
+ qreal ch = obj->contentHeight();
+
+ QVERIFY(cw > 0);
+ QVERIFY(ch > 0);
+
+ QCOMPARE(obj->padding(), 10.0);
+ QCOMPARE(obj->topPadding(), 20.0);
+ QCOMPARE(obj->leftPadding(), 30.0);
+ QCOMPARE(obj->rightPadding(), 40.0);
+ QCOMPARE(obj->bottomPadding(), 50.0);
+
+ QCOMPARE(obj->implicitWidth(), qCeil(cw) + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), qCeil(ch) + obj->topPadding() + obj->bottomPadding());
+
+ obj->setTopPadding(2.25);
+ QCOMPARE(obj->topPadding(), 2.25);
+ QCOMPARE(obj->implicitHeight(), qCeil(ch) + obj->topPadding() + obj->bottomPadding());
+
+ obj->setLeftPadding(3.75);
+ QCOMPARE(obj->leftPadding(), 3.75);
+ QCOMPARE(obj->implicitWidth(), qCeil(cw) + obj->leftPadding() + obj->rightPadding());
+
+ obj->setRightPadding(4.4);
+ QCOMPARE(obj->rightPadding(), 4.4);
+ QCOMPARE(obj->implicitWidth(), qCeil(cw) + obj->leftPadding() + obj->rightPadding());
+
+ obj->setBottomPadding(1.11);
+ QCOMPARE(obj->bottomPadding(), 1.11);
+ QCOMPARE(obj->implicitHeight(), qCeil(ch) + obj->topPadding() + obj->bottomPadding());
+
+ obj->setText("Qt");
+ QVERIFY(obj->contentWidth() < cw);
+ QCOMPARE(obj->contentHeight(), ch);
+ cw = obj->contentWidth();
+
+ QCOMPARE(obj->implicitWidth(), qCeil(cw) + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), qCeil(ch) + obj->topPadding() + obj->bottomPadding());
+
+ obj->setFont(QFont("Courier", 96));
+ QVERIFY(obj->contentWidth() > cw);
+ QVERIFY(obj->contentHeight() > ch);
+ cw = obj->contentWidth();
+ ch = obj->contentHeight();
+
+ QCOMPARE(obj->implicitWidth(), qCeil(cw) + obj->leftPadding() + obj->rightPadding());
+ QCOMPARE(obj->implicitHeight(), qCeil(ch) + obj->topPadding() + obj->bottomPadding());
+
+ obj->resetTopPadding();
+ QCOMPARE(obj->topPadding(), 10.0);
+ obj->resetLeftPadding();
+ QCOMPARE(obj->leftPadding(), 10.0);
+ obj->resetRightPadding();
+ QCOMPARE(obj->rightPadding(), 10.0);
+ obj->resetBottomPadding();
+ QCOMPARE(obj->bottomPadding(), 10.0);
+
+ obj->resetPadding();
+ QCOMPARE(obj->padding(), 0.0);
+ QCOMPARE(obj->topPadding(), 0.0);
+ QCOMPARE(obj->leftPadding(), 0.0);
+ QCOMPARE(obj->rightPadding(), 0.0);
+ QCOMPARE(obj->bottomPadding(), 0.0);
+
+ delete root;
+}
+
QTEST_MAIN(tst_qquicktextinput)
#include "tst_qquicktextinput.moc"
diff --git a/tests/auto/quick/qquickview/data/error2.qml b/tests/auto/quick/qquickview/data/error2.qml
new file mode 100644
index 0000000000..1d754b64f0
--- /dev/null
+++ b/tests/auto/quick/qquickview/data/error2.qml
@@ -0,0 +1,4 @@
+import QtQuick.Window 2.0
+
+Window {
+}
diff --git a/tests/auto/quick/qquickview/tst_qquickview.cpp b/tests/auto/quick/qquickview/tst_qquickview.cpp
index a980c69140..7ee24bf3d4 100644
--- a/tests/auto/quick/qquickview/tst_qquickview.cpp
+++ b/tests/auto/quick/qquickview/tst_qquickview.cpp
@@ -187,6 +187,15 @@ void tst_QQuickView::errors()
QVERIFY(view.status() == QQuickView::Error);
QVERIFY(view.errors().count() == 1);
}
+
+ {
+ QQuickView view;
+ QQmlTestMessageHandler messageHandler;
+ view.setSource(testFileUrl("error2.qml"));
+ QVERIFY(view.status() == QQuickView::Error);
+ QVERIFY(view.errors().count() == 1);
+ view.show();
+ }
}
void tst_QQuickView::engine()
diff --git a/tests/auto/quick/qquickwindow/BLACKLIST b/tests/auto/quick/qquickwindow/BLACKLIST
index 1201ef12f0..8a19a679a3 100644
--- a/tests/auto/quick/qquickwindow/BLACKLIST
+++ b/tests/auto/quick/qquickwindow/BLACKLIST
@@ -1,2 +1,4 @@
+[cursor]
+*
[testWindowVisibilityOrder]
osx
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 93c3a34b39..333c210713 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -504,7 +504,7 @@ void tst_qquickwindow::touchEvent_basic()
window->resize(250, 250);
window->setPosition(100, 100);
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowActive(window));
TestTouchItem *bottomItem = new TestTouchItem(window->contentItem());
bottomItem->setObjectName("Bottom Item");
@@ -635,7 +635,7 @@ void tst_qquickwindow::touchEvent_propagation()
window->setPosition(100, 100);
window->setTitle(QTest::currentTestFunction());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowActive(window));
TestTouchItem *bottomItem = new TestTouchItem(window->contentItem());
bottomItem->setObjectName("Bottom Item");
@@ -769,18 +769,18 @@ void tst_qquickwindow::touchEvent_cancel()
window->setPosition(100, 100);
window->setTitle(QTest::currentTestFunction());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowActive(window));
TestTouchItem *item = new TestTouchItem(window->contentItem());
item->setPosition(QPointF(50, 50));
item->setSize(QSizeF(150, 150));
- QPointF pos(10, 10);
- QTest::touchEvent(window, touchDevice).press(0, item->mapToScene(pos).toPoint(),window);
+ QPointF pos(50, 50);
+ QTest::touchEvent(window, touchDevice).press(0, item->mapToScene(pos).toPoint(), window);
QCoreApplication::processEvents();
QTRY_COMPARE(item->lastEvent.touchPoints.count(), 1);
- TouchEventData d = makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(item,pos));
+ TouchEventData d = makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(item, pos));
COMPARE_TOUCH_DATA(item->lastEvent, d);
item->reset();
@@ -803,7 +803,7 @@ void tst_qquickwindow::touchEvent_reentrant()
window->setPosition(100, 100);
window->setTitle(QTest::currentTestFunction());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowActive(window));
TestTouchItem *item = new TestTouchItem(window->contentItem());
@@ -993,7 +993,7 @@ void tst_qquickwindow::mouseFiltering()
window->setPosition(100, 100);
window->setTitle(QTest::currentTestFunction());
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowActive(window));
TestTouchItem *bottomItem = new TestTouchItem(window->contentItem());
bottomItem->setObjectName("Bottom Item");
@@ -1452,7 +1452,7 @@ void tst_qquickwindow::cursor()
clippedItem.setParentItem(&clippingItem);
window.show();
- QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowActive(&window));
// Position the cursor over the parent and child item and the clipped section of clippedItem.
QTest::mouseMove(&window, QPoint(100, 100));
@@ -1813,7 +1813,7 @@ void tst_qquickwindow::crashWhenHoverItemDeleted()
QVERIFY(!window.isNull());
window->setTitle(QTest::currentTestFunction());
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QTest::qWaitForWindowActive(window.data());
// Simulate a move from the first rectangle to the second. Crash will happen in here
// Moving instantaneously from (0, 99) to (0, 102) does not cause the crash
@@ -1852,7 +1852,7 @@ void tst_qquickwindow::qobjectEventFilter_touch()
window.setPosition(100, 100);
window.setTitle(QTest::currentTestFunction());
window.show();
- QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowActive(&window));
TestTouchItem *item = new TestTouchItem(window.contentItem());
item->setSize(QSizeF(150, 150));
@@ -1878,7 +1878,7 @@ void tst_qquickwindow::qobjectEventFilter_key()
window.setPosition(100, 100);
window.setTitle(QTest::currentTestFunction());
window.show();
- QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowActive(&window));
TestTouchItem *item = new TestTouchItem(window.contentItem());
item->setSize(QSizeF(150, 150));
@@ -1907,8 +1907,7 @@ void tst_qquickwindow::qobjectEventFilter_mouse()
window.setPosition(100, 100);
window.setTitle(QTest::currentTestFunction());
window.show();
-
- QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowActive(&window));
TestTouchItem *item = new TestTouchItem(window.contentItem());
item->setSize(QSizeF(150, 150));
@@ -1917,6 +1916,7 @@ void tst_qquickwindow::qobjectEventFilter_mouse()
item->installEventFilter(&eventFilter);
QPoint point = item->mapToScene(QPointF(10, 10)).toPoint();
+ QTest::mouseMove(&window, point);
QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, point);
QVERIFY(eventFilter.events.contains((int)QEvent::MouseButtonPress));
@@ -2056,44 +2056,108 @@ public:
static int deleted;
};
+class GlRenderJob : public QRunnable
+{
+public:
+ GlRenderJob(GLubyte *buf) : readPixel(buf), mutex(0), condition(0) {}
+ ~GlRenderJob() {}
+ void run() {
+ QOpenGLContext::currentContext()->functions()->glClearColor(1.0f, 0, 0, 1.0f);
+ QOpenGLContext::currentContext()->functions()->glClear(GL_COLOR_BUFFER_BIT);
+ QOpenGLContext::currentContext()->functions()->glReadPixels(0, 0, 1, 1, GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ (void *)readPixel);
+ if (mutex) {
+ mutex->lock();
+ condition->wakeOne();
+ mutex->unlock();
+ }
+ }
+ GLubyte *readPixel;
+ QMutex *mutex;
+ QWaitCondition *condition;
+};
+
int RenderJob::deleted = 0;
void tst_qquickwindow::testRenderJob()
{
QList<QQuickWindow::RenderStage> completedJobs;
- QQuickWindow window;
- window.setTitle(QTest::currentTestFunction());
-
QQuickWindow::RenderStage stages[] = {
QQuickWindow::BeforeSynchronizingStage,
QQuickWindow::AfterSynchronizingStage,
QQuickWindow::BeforeRenderingStage,
QQuickWindow::AfterRenderingStage,
- QQuickWindow::AfterSwapStage
+ QQuickWindow::AfterSwapStage,
+ QQuickWindow::NoStage
};
- // Schedule the jobs
- for (int i=0; i<5; ++i)
- window.scheduleRenderJob(new RenderJob(stages[i], &completedJobs), stages[i]);
- window.show();
- QTRY_COMPARE(completedJobs.size(), 5);
+ const int numJobs = 6;
- for (int i=0; i<5; ++i) {
- QCOMPARE(completedJobs.at(i), stages[i]);
+ {
+ QQuickWindow window;
+ window.setTitle(QTest::currentTestFunction());
+ RenderJob::deleted = 0;
+
+ // Schedule the jobs
+ for (int i = 0; i < numJobs; ++i)
+ window.scheduleRenderJob(new RenderJob(stages[i], &completedJobs), stages[i]);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ // All jobs should be deleted
+ QTRY_COMPARE(RenderJob::deleted, numJobs);
+
+ // The NoStage job is not completed, if it is issued when there is no context,
+ // but the rest will be queued and completed once relevant render stage is hit.
+ QCOMPARE(completedJobs.size(), numJobs - 1);
+
+ // Verify jobs were completed in correct order
+ for (int i = 0; i < numJobs - 1; ++i)
+ QCOMPARE(completedJobs.at(i), stages[i]);
+
+
+ // Check that NoStage job gets executed if it is scheduled when window is exposed
+ completedJobs.clear();
+ RenderJob::deleted = 0;
+ window.scheduleRenderJob(new RenderJob(QQuickWindow::NoStage, &completedJobs),
+ QQuickWindow::NoStage);
+ QTRY_COMPARE(RenderJob::deleted, 1);
+ QCOMPARE(completedJobs.size(), 1);
+
+ // Do a synchronized GL job.
+ GLubyte readPixel[4] = {0, 0, 0, 0};
+ GlRenderJob *glJob = new GlRenderJob(readPixel);
+ if (window.openglContext()->thread() != QThread::currentThread()) {
+ QMutex mutex;
+ QWaitCondition condition;
+ glJob->mutex = &mutex;
+ glJob->condition = &condition;
+ mutex.lock();
+ window.scheduleRenderJob(glJob, QQuickWindow::NoStage);
+ condition.wait(&mutex);
+ mutex.unlock();
+ } else {
+ window.scheduleRenderJob(glJob, QQuickWindow::NoStage);
+ }
+ QCOMPARE(int(readPixel[0]), 255);
+ QCOMPARE(int(readPixel[1]), 0);
+ QCOMPARE(int(readPixel[2]), 0);
+ QCOMPARE(int(readPixel[3]), 255);
}
- // Verify that jobs are deleted when window has not been rendered at all...
+ // Verify that jobs are deleted when window is not rendered at all
completedJobs.clear();
RenderJob::deleted = 0;
{
QQuickWindow window2;
- for (int i=0; i<5; ++i) {
+ for (int i = 0; i < numJobs; ++i) {
window2.scheduleRenderJob(new RenderJob(stages[i], &completedJobs), stages[i]);
}
}
+ QTRY_COMPARE(RenderJob::deleted, numJobs);
QCOMPARE(completedJobs.size(), 0);
- QCOMPARE(RenderJob::deleted, 5);
}
class EventCounter : public QQuickRectangle
@@ -2152,7 +2216,7 @@ void tst_qquickwindow::testHoverChildMouseEventFilter()
window.setPosition(100, 100);
window.setTitle(QTest::currentTestFunction());
window.show();
- QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowActive(&window));
EventCounter *bottomItem = new EventCounter(window.contentItem());
bottomItem->setObjectName("Bottom Item");
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index c2b7a4cc8d..5593fd94f6 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -74,8 +74,8 @@ QUICKTESTS = \
qquickview \
qquickcanvasitem \
qquickscreen \
- touchmouse
-
+ touchmouse \
+ scenegraph
SUBDIRS += $$PUBLICTESTS
diff --git a/tests/auto/quick/scenegraph/data/mipmap_large.png b/tests/auto/quick/scenegraph/data/mipmap_large.png
index 9cb0fc7de1..1b6d99c45c 100644
--- a/tests/auto/quick/scenegraph/data/mipmap_large.png
+++ b/tests/auto/quick/scenegraph/data/mipmap_large.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/mipmap_small.png b/tests/auto/quick/scenegraph/data/mipmap_small.png
index dc5216fb6c..2e53012ef5 100644
--- a/tests/auto/quick/scenegraph/data/mipmap_small.png
+++ b/tests/auto/quick/scenegraph/data/mipmap_small.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/render_Mipmap.qml b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
index 6d9191c5ac..9bd585373a 100644
--- a/tests/auto/quick/scenegraph/data/render_Mipmap.qml
+++ b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
@@ -32,6 +32,7 @@
****************************************************************************/
import QtQuick 2.3
+import QtQuick.Window 2.2
/*
The test verifies that scaled down mipmapped images contains
@@ -39,8 +40,8 @@ import QtQuick 2.3
#samples: 2
PixelPos R G B Error-tolerance
- #final: 0 0 0.33 0.33 0.33 0.1
- #final: 1 0 0.33 0.33 0.33 0.1
+ #final: 0 0 0.25 0.25 0.25 0.1
+ #final: 1 0 0.25 0.25 0.25 0.1
*/
RenderTestBase
@@ -52,7 +53,7 @@ RenderTestBase
source: "mipmap_small.png"
mipmap: true
smooth: false
- scale: 1 / width;
+ scale: 1 / (width * Screen.devicePixelRatio);
}
Image {
@@ -62,7 +63,7 @@ RenderTestBase
source: "mipmap_large.png"
mipmap: true
smooth: false
- scale: 1 / width;
+ scale: 1 / (width * Screen.devicePixelRatio);
}
onEnterFinalStage: finalStageComplete = true;
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index d2d3643ca8..80672e234e 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -33,11 +33,17 @@
#include <qtest.h>
+#include <QOffscreenSurface>
+#include <QOpenGLContext>
+#include <QOpenGLFunctions>
+
#include <QtQuick>
+#include <QtQml>
#include <private/qopenglcontext_p.h>
+#include <private/qsgcontext_p.h>
+#include <private/qsgrenderloop_p.h>
-#include <QtQml>
class PerPixelRect : public QQuickItem
{
@@ -97,6 +103,12 @@ private slots:
void render();
void hideWithOtherContext();
+
+ void createTextureFromImage_data();
+ void createTextureFromImage();
+
+private:
+ bool m_brokenMipmapSupport;
};
template <typename T> class ScopedList : public QList<T> {
@@ -107,6 +119,42 @@ public:
void tst_SceneGraph::initTestCase()
{
qmlRegisterType<PerPixelRect>("SceneGraphTest", 1, 0, "PerPixelRect");
+
+ QSGRenderLoop *loop = QSGRenderLoop::instance();
+ qDebug() << "RenderLoop: " << loop;
+
+ QOpenGLContext context;
+ context.setFormat(loop->sceneGraphContext()->defaultSurfaceFormat());
+ context.create();
+ QSurfaceFormat format = context.format();
+
+ QOffscreenSurface surface;
+ surface.setFormat(format);
+ surface.create();
+ if (!context.makeCurrent(&surface))
+ qFatal("Failed to create a GL context...");
+
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ qDebug() << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize();
+ qDebug() << "Depth Buffer: " << format.depthBufferSize();
+ qDebug() << "Stencil Buffer: " << format.stencilBufferSize();
+ qDebug() << "Samples: " << format.samples();
+ int textureSize;
+ funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &textureSize);
+ qDebug() << "Max Texture Size: " << textureSize;
+ qDebug() << "GL_VENDOR: " << (const char *) funcs->glGetString(GL_VENDOR);
+ qDebug() << "GL_RENDERER: " << (const char *) funcs->glGetString(GL_RENDERER);
+ QByteArray version = (const char *) funcs->glGetString(GL_VERSION);
+ qDebug() << "GL_VERSION: " << version.constData();
+ QSet<QByteArray> exts = context.extensions();
+ QByteArray all;
+ foreach (const QByteArray &e, exts) all += ' ' + e;
+ qDebug() << "GL_EXTENSIONS: " << all.constData();
+
+ m_brokenMipmapSupport = version.contains("Mesa 10.1") || version.contains("Mesa 9.");
+ qDebug() << "Broken Mipmap: " << m_brokenMipmapSupport;
+
+ context.doneCurrent();
}
QQuickView *createView(const QString &file, QWindow *parent = 0, int x = -1, int y = -1, int w = -1, int h = -1)
@@ -210,7 +258,7 @@ void tst_SceneGraph::manyWindows_data()
struct ShareContextResetter {
public:
- ~ShareContextResetter() { QOpenGLContextPrivate::setGlobalShareContext(0); }
+ ~ShareContextResetter() { qt_gl_set_global_share_context(0); }
};
void tst_SceneGraph::manyWindows()
@@ -223,7 +271,7 @@ void tst_SceneGraph::manyWindows()
ShareContextResetter cleanup; // To avoid dangling pointer in case of test-failure.
if (shared) {
QVERIFY(sharedGLContext.create());
- QOpenGLContextPrivate::setGlobalShareContext(&sharedGLContext);
+ qt_gl_set_global_share_context(&sharedGLContext);
}
QScopedPointer<QWindow> parent;
@@ -297,8 +345,8 @@ struct Sample {
.arg(color.redF()).arg(color.greenF()).arg(color.blueF());
}
- bool check(const QImage &image) {
- QColor color(image.pixel(x, y));
+ bool check(const QImage &image, qreal scale) {
+ QColor color(image.pixel(x * scale, y * scale));
return qAbs(color.redF() - r) <= tolerance
&& qAbs(color.greenF() - g) <= tolerance
&& qAbs(color.blueF() - b) <= tolerance;
@@ -368,11 +416,11 @@ void tst_SceneGraph::render_data()
<< "data/render_BreakOpacityBatch.qml"
<< "data/render_OutOfFloatRange.qml"
<< "data/render_StackingOrder.qml"
- << "data/render_Mipmap.qml"
<< "data/render_ImageFiltering.qml"
<< "data/render_bug37422.qml"
- << "data/render_OpacityThroughBatchRoot.qml"
- ;
+ << "data/render_OpacityThroughBatchRoot.qml";
+ if (!m_brokenMipmapSupport)
+ files << "data/render_Mipmap.qml";
QRegExp sampleCount("#samples: *(\\d+)");
// X:int Y:int R:float G:float B:float Error:float
@@ -428,11 +476,18 @@ void tst_SceneGraph::render()
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
+ // We're checking actual pixels, so scale up the sample point to the top-left of the
+ // 2x2 pixel block and hope that this is good enough. Ideally, view and content
+ // would be in identical coordinate space, meaning pixels, but we're not in an
+ // ideal world.
+ // Just keep this in mind when writing tests.
+ qreal scale = view.devicePixelRatio();
+
// Grab the window and check all our base stage samples
QImage content = view.grabWindow();
for (int i=0; i<baseStage.size(); ++i) {
Sample sample = baseStage.at(i);
- QVERIFY2(sample.check(content), qPrintable(sample.toString(content)));
+ QVERIFY2(sample.check(content, scale), qPrintable(sample.toString(content)));
}
// Put the qml file into the final stage and wait for it to
@@ -445,7 +500,7 @@ void tst_SceneGraph::render()
content = view.grabWindow();
for (int i=0; i<finalStage.size(); ++i) {
Sample sample = finalStage.at(i);
- QVERIFY2(sample.check(content), qPrintable(sample.toString(content)));
+ QVERIFY2(sample.check(content, scale), qPrintable(sample.toString(content)));
}
}
@@ -482,6 +537,34 @@ void tst_SceneGraph::hideWithOtherContext()
QVERIFY(!renderingOnMainThread || QOpenGLContext::currentContext() != &context);
}
+void tst_SceneGraph::createTextureFromImage_data()
+{
+ QImage rgba(64, 64, QImage::Format_ARGB32_Premultiplied);
+ QImage rgb(64, 64, QImage::Format_RGB32);
+
+ QTest::addColumn<QImage>("image");
+ QTest::addColumn<uint>("flags");
+ QTest::addColumn<bool>("expectedAlpha");
+
+ QTest::newRow("rgb") << rgb << uint(0) << false;
+ QTest::newRow("argb") << rgba << uint(0) << true;
+ QTest::newRow("rgb,alpha") << rgb << uint(QQuickWindow::TextureHasAlphaChannel) << false;
+ QTest::newRow("argb,alpha") << rgba << uint(QQuickWindow::TextureHasAlphaChannel) << true;
+ QTest::newRow("rgb,!alpha") << rgb << uint(QQuickWindow::TextureIsOpaque) << false;
+ QTest::newRow("argb,!alpha") << rgba << uint(QQuickWindow::TextureIsOpaque) << false;
+}
+
+void tst_SceneGraph::createTextureFromImage()
+{
+ QFETCH(QImage, image);
+ QFETCH(uint, flags);
+ QFETCH(bool, expectedAlpha);
+
+ QQuickView view;
+ QScopedPointer<QSGTexture> texture(view.createTextureFromImage(image, (QQuickWindow::CreateTextureOptions) flags));
+ QCOMPARE(texture->hasAlphaChannel(), expectedAlpha);
+}
+
#include "tst_scenegraph.moc"
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index 5b9111d448..86d61a0c23 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -72,18 +72,30 @@ void QQuickViewTestUtil::moveMouseAway(QQuickView *window)
#endif
}
+void QQuickViewTestUtil::moveAndRelease(QQuickView *window, const QPoint &position)
+{
+ QTest::mouseMove(window, position);
+ QTest::mouseRelease(window, Qt::LeftButton, 0, position);
+}
+
+void QQuickViewTestUtil::moveAndPress(QQuickView *window, const QPoint &position)
+{
+ QTest::mouseMove(window, position);
+ QTest::mousePress(window, Qt::LeftButton, 0, position);
+}
+
void QQuickViewTestUtil::flick(QQuickView *window, const QPoint &from, const QPoint &to, int duration)
{
const int pointCount = 5;
QPoint diff = to - from;
// send press, five equally spaced moves, and release.
- QTest::mousePress(window, Qt::LeftButton, 0, from);
+ moveAndPress(window, from);
for (int i = 0; i < pointCount; ++i)
QTest::mouseMove(window, from + (i+1)*diff/pointCount, duration / pointCount);
- QTest::mouseRelease(window, Qt::LeftButton, 0, to);
+ moveAndRelease(window, to);
QTest::qWait(50);
}
diff --git a/tests/auto/quick/shared/viewtestutil.h b/tests/auto/quick/shared/viewtestutil.h
index 8c5f5c54e6..1643eca979 100644
--- a/tests/auto/quick/shared/viewtestutil.h
+++ b/tests/auto/quick/shared/viewtestutil.h
@@ -48,6 +48,8 @@ namespace QQuickViewTestUtil
void centerOnScreen(QQuickView *window, const QSize &size);
void centerOnScreen(QQuickView *window);
void moveMouseAway(QQuickView *window);
+ void moveAndPress(QQuickView *window, const QPoint &position);
+ void moveAndRelease(QQuickView *window, const QPoint &position);
QList<int> adjustIndexesForAddDisplaced(const QList<int> &indexes, int index, int count);
QList<int> adjustIndexesForMove(const QList<int> &indexes, int from, int to, int count);
diff --git a/tests/benchmarks/script/qjsvalue/tst_qjsvalue.cpp b/tests/benchmarks/script/qjsvalue/tst_qjsvalue.cpp
index a8e99b5cf9..b5147dbf01 100644
--- a/tests/benchmarks/script/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/benchmarks/script/qjsvalue/tst_qjsvalue.cpp
@@ -34,12 +34,6 @@
#include <qtest.h>
#include <QJSEngine>
#include <QJSValue>
-#include <private/v8.h>
-
-QT_BEGIN_NAMESPACE
-extern Q_QML_EXPORT v8::Local<v8::Context> qt_QJSEngineV8Context(QJSEngine *);
-extern Q_QML_EXPORT v8::Local<v8::Value> qt_QJSValueV8Value(const QJSValue &);
-QT_END_NAMESPACE
class tst_QJSValue : public QObject
{
@@ -49,16 +43,12 @@ public:
private slots:
void fillArray();
- void fillArray_V8();
void property();
- void property_V8();
void setProperty();
- void setProperty_V8();
void call();
- void call_V8();
};
void tst_QJSValue::fillArray()
@@ -72,20 +62,6 @@ void tst_QJSValue::fillArray()
}
}
-void tst_QJSValue::fillArray_V8()
-{
- QJSEngine eng;
- static const int ArrayLength = 10000;
- QJSValue array = eng.newArray(ArrayLength);
-
- v8::HandleScope handleScope;
- v8::Local<v8::Array> v8array = qt_QJSValueV8Value(array).As<v8::Array>();
- QBENCHMARK {
- for (int i = 0; i < ArrayLength; ++i)
- v8array->Set(i, v8::Number::New(i));
- }
-}
-
void tst_QJSValue::property()
{
QJSEngine eng;
@@ -98,23 +74,6 @@ void tst_QJSValue::property()
}
}
-void tst_QJSValue::property_V8()
-{
- QJSEngine eng;
- QJSValue object = eng.newObject();
- QString propertyName = QString::fromLatin1("foo");
- object.setProperty(propertyName, 123);
- QVERIFY(object.property(propertyName).isNumber());
-
- v8::HandleScope handleScope;
- v8::Local<v8::Object> v8object = qt_QJSValueV8Value(object).As<v8::Object>();
- v8::Local<v8::String> v8propertyName = v8::String::New("foo");
- QVERIFY(v8object->Get(v8propertyName)->IsNumber());
- QBENCHMARK {
- v8object->Get(v8propertyName);
- }
-}
-
void tst_QJSValue::setProperty()
{
QJSEngine eng;
@@ -126,24 +85,6 @@ void tst_QJSValue::setProperty()
}
}
-void tst_QJSValue::setProperty_V8()
-{
- QJSEngine eng;
- QJSValue object = eng.newObject();
-
- v8::HandleScope handleScope;
- // A context scope is needed for v8::Object::Set(), otherwise we crash.
- v8::Local<v8::Context> context = qt_QJSEngineV8Context(&eng);
- v8::Context::Scope contextScope(context);
-
- v8::Local<v8::Object> v8object = qt_QJSValueV8Value(object).As<v8::Object>();
- v8::Local<v8::String> v8propertyName = v8::String::New("foo");
- v8::Local<v8::Value> v8value = v8::Number::New(123);
- QBENCHMARK {
- v8object->Set(v8propertyName, v8value);
- }
-}
-
#define TEST_FUNCTION_SOURCE "(function() { return 123; })"
void tst_QJSValue::call()
@@ -158,24 +99,6 @@ void tst_QJSValue::call()
}
}
-void tst_QJSValue::call_V8()
-{
- QJSEngine eng;
- QJSValue fun = eng.evaluate(TEST_FUNCTION_SOURCE);
- QVERIFY(fun.isCallable());
-
- v8::HandleScope handleScope;
- v8::Local<v8::Context> context = qt_QJSEngineV8Context(&eng);
- v8::Context::Scope contextScope(context);
-
- v8::Local<v8::Function> v8fun = qt_QJSValueV8Value(fun).As<v8::Function>();
- v8::Local<v8::Object> v8thisObject = v8::Object::New();
- QVERIFY(v8fun->Call(v8thisObject, /*argc=*/0, /*argv=*/0)->IsNumber());
- QBENCHMARK {
- v8fun->Call(v8thisObject, /*argc=*/0, /*argv=*/0);
- }
-}
-
QTEST_MAIN(tst_QJSValue)
#include "tst_qjsvalue.moc"
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 0553553e85..206788c061 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -53,6 +53,7 @@
#include <QFileInfo>
#include <QRegularExpression>
#include <QStringList>
+#include <QScopedPointer>
#include <QDebug>
#include <QStandardPaths>
#include <QTranslator>
@@ -67,8 +68,8 @@
#include <cstdlib>
#define VERSION_MAJ 1
-#define VERSION_MIN 0
-#define VERSION_STR "1.0"
+#define VERSION_MIN 1
+#define VERSION_STR "1.1"
#define FILE_OPEN_EVENT_WAIT_TIME 3000 // ms
@@ -163,13 +164,20 @@ class LoadWatcher : public QObject
public:
LoadWatcher(QQmlApplicationEngine *e, int expected)
: QObject(e)
+ , earlyExit(false)
, expect(expected)
, haveOne(false)
{
connect(e, SIGNAL(objectCreated(QObject*,QUrl)),
this, SLOT(checkFinished(QObject*)));
+ // QQmlApplicationEngine also connects quit() to QCoreApplication::quit
+ // but if called before exec() then QCoreApplication::quit does nothing
+ connect(e, SIGNAL(quit()),
+ this, SLOT(quit()));
}
+ bool earlyExit;
+
private:
void contain(QObject *o, const QUrl &containPath);
void checkForWindow(QObject *o);
@@ -196,6 +204,11 @@ public Q_SLOTS:
exit(2);//Different return code from qFatal
}
}
+
+ void quit() {
+ //Will be checked before calling exec()
+ earlyExit = true;
+ }
#ifdef QT_GUI_LIB
void onOpenGlContextCreated(QOpenGLContext *context);
#endif
@@ -293,11 +306,10 @@ void printVersion()
void printUsage()
{
- printf("Usage: qml [options] [files]\n");
+ printf("Usage: qml [options] [files] [-- args]\n");
printf("\n");
- printf("Any argument ending in .qml will be treated as a QML file to be loaded.\n");
+ printf("Any unknown argument before '--' will be treated as a QML file to be loaded.\n");
printf("Any number of QML files can be loaded. They will share the same engine.\n");
- printf("Any argument which is not a recognized option and which does not end in .qml will be ignored.\n");
printf("'gui' application type is only available if the QtGui module is available.\n");
printf("'widget' application type is only available if the QtWidgets module is available.\n");
printf("\n");
@@ -434,8 +446,8 @@ int main(int argc, char *argv[])
app->setOrganizationName("QtProject");
app->setOrganizationDomain("qt-project.org");
- qmlRegisterType<Config>("QmlRuntime.Config", VERSION_MAJ, VERSION_MIN, "Configuration");
- qmlRegisterType<PartialScene>("QmlRuntime.Config", VERSION_MAJ, VERSION_MIN, "PartialScene");
+ qmlRegisterType<Config>("QmlRuntime.Config", 1, 0, "Configuration");
+ qmlRegisterType<PartialScene>("QmlRuntime.Config", 1, 0, "PartialScene");
QQmlApplicationEngine e;
QStringList files;
QString confFile;
@@ -444,7 +456,7 @@ int main(int argc, char *argv[])
//Handle main arguments
QStringList argList = app->arguments();
- for (int i = 0; i < argList.count(); i++) {
+ for (int i = 1; i < argList.count(); i++) {
const QString &arg = argList[i];
if (arg == QLatin1String("-quiet"))
quietMode = true;
@@ -492,9 +504,7 @@ int main(int argc, char *argv[])
} else if (arg == QLatin1String("-desktop")) {
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
} else {
- //If it ends in .qml, treat it as a file. Else ignore it
- if (arg.endsWith(".qml"))
- files << arg;
+ files << arg;
}
}
@@ -538,7 +548,7 @@ int main(int argc, char *argv[])
loadConf(confFile, !verboseMode);
//Load files
- LoadWatcher lw(&e, files.count());
+ QScopedPointer<LoadWatcher> lw(new LoadWatcher(&e, files.count()));
// Load dummy data before loading QML-files
if (!dummyDir.isEmpty() && QFileInfo (dummyDir).isDir())
@@ -570,6 +580,9 @@ int main(int argc, char *argv[])
}
}
+ if (lw->earlyExit)
+ return 0;
+
return app->exec();
}
diff --git a/tools/qmleasing/splineeditor.cpp b/tools/qmleasing/splineeditor.cpp
index a2ddc056df..b957cab4fe 100644
--- a/tools/qmleasing/splineeditor.cpp
+++ b/tools/qmleasing/splineeditor.cpp
@@ -680,6 +680,7 @@ void SplineEditor::setEasingCurve(const QString &code)
const QStringList stringList = cleanCode.split(QLatin1Char(','), QString::SkipEmptyParts);
if (stringList.count() >= 6 && (stringList.count() % 6 == 0)) {
QList<qreal> realList;
+ realList.reserve(stringList.count());
foreach (const QString &string, stringList) {
bool ok;
realList.append(string.toDouble(&ok));
@@ -687,7 +688,9 @@ void SplineEditor::setEasingCurve(const QString &code)
return;
}
QList<QPointF> points;
- for (int i = 0; i < realList.count() / 2; ++i)
+ const int count = realList.count() / 2;
+ points.reserve(count);
+ for (int i = 0; i < count; ++i)
points.append(QPointF(realList.at(i * 2), realList.at(i * 2 + 1)));
if (points.last() == QPointF(1.0, 1.0)) {
QEasingCurve easingCurve(QEasingCurve::BezierSpline);
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index 37f2962a14..beb47e43c1 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -35,7 +35,7 @@
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
#include <private/qv4codegen_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qqmlpool_p.h>
#include <private/qqmlirbuilder_p.h>
diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp
index db9d1b9cda..53e520cd1f 100644
--- a/tools/qmljs/qmljs.cpp
+++ b/tools/qmljs/qmljs.cpp
@@ -44,6 +44,7 @@
#include "private/qv4mm_p.h"
#include "private/qv4context_p.h"
#include "private/qv4script_p.h"
+#include "private/qv4string_p.h"
#ifdef V4_ENABLE_JIT
# include "private/qv4isel_masm_p.h"
@@ -72,7 +73,7 @@ struct Print: FunctionObject
};
V4_OBJECT(FunctionObject)
- static ReturnedValue call(Managed *, CallData *callData)
+ static ReturnedValue call(const Managed *, CallData *callData)
{
for (int i = 0; i < callData->argc; ++i) {
QString s = callData->args[i].toQStringNoThrow();
@@ -98,9 +99,9 @@ struct GC: public FunctionObject
};
V4_OBJECT(FunctionObject)
- static ReturnedValue call(Managed *m, CallData *)
+ static ReturnedValue call(const Managed *m, CallData *)
{
- static_cast<GC *>(m)->engine()->memoryManager->runGC();
+ static_cast<const GC *>(m)->engine()->memoryManager->runGC();
return Encode::undefined();
}
};
@@ -113,7 +114,7 @@ static void showException(QV4::ExecutionContext *ctx, const QV4::Value &exceptio
{
QV4::Scope scope(ctx);
QV4::ScopedValue ex(scope, exception);
- QV4::ErrorObject *e = ex->asErrorObject();
+ QV4::ErrorObject *e = ex->as<QV4::ErrorObject>();
if (!e) {
std::cerr << "Uncaught exception: " << qPrintable(ex->toQString()) << std::endl;
} else {
@@ -187,11 +188,10 @@ int main(int argc, char *argv[])
QV4::Scope scope(&vm);
QV4::ScopedContext ctx(scope, vm.rootContext());
- QV4::ScopedObject globalObject(scope, vm.globalObject());
QV4::ScopedObject print(scope, vm.memoryManager->alloc<builtins::Print>(ctx));
- globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("print"))).getPointer(), print);
+ vm.globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("print"))).getPointer(), print);
QV4::ScopedObject gc(scope, vm.memoryManager->alloc<builtins::GC>(ctx));
- globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("gc"))).getPointer(), gc);
+ vm.globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("gc"))).getPointer(), gc);
foreach (const QString &fn, args) {
QFile file(fn);
diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp
index cd81a5bad6..a1161c635a 100644
--- a/tools/qmllint/main.cpp
+++ b/tools/qmllint/main.cpp
@@ -37,7 +37,7 @@
#include <QCommandLineParser>
#include <QCoreApplication>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljsengine_p.h>
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 96c23ae268..c7539ac874 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -685,7 +685,9 @@ private:
qml->writeScriptBinding(QLatin1String("name"), enquote(QString::fromUtf8(e.name())));
QList<QPair<QString, QString> > namesValues;
- for (int index = 0; index < e.keyCount(); ++index) {
+ const int keyCount = e.keyCount();
+ namesValues.reserve(keyCount);
+ for (int index = 0; index < keyCount; ++index) {
namesValues.append(qMakePair(enquote(QString::fromUtf8(e.key(index))), QString::number(e.value(index))));
}
diff --git a/tools/qmlprofiler/commandlistener.cpp b/tools/qmlprofiler/commandlistener.cpp
index 1d538d8a3d..369d095725 100644
--- a/tools/qmlprofiler/commandlistener.cpp
+++ b/tools/qmlprofiler/commandlistener.cpp
@@ -35,24 +35,7 @@
#include "constants.h"
#include <QtCore/QTextStream>
-CommandListener::CommandListener(QObject *parent)
- : QThread(parent)
- , m_stopRequested(false)
+void CommandListener::readCommand()
{
-}
-
-void CommandListener::run()
-{
- QString line;
- QTextStream in(stdin, QIODevice::ReadOnly);
- do {
- line = in.readLine();
- line = line.trimmed();
- if (!line.isEmpty()) {
- emit command(line);
- if (line == QLatin1String(Constants::CMD_QUIT)
- || line == QLatin1String(Constants::CMD_QUIT2))
- return;
- }
- } while (!m_stopRequested && !line.isNull());
+ emit command(QTextStream(stdin).readLine());
}
diff --git a/tools/qmlprofiler/commandlistener.h b/tools/qmlprofiler/commandlistener.h
index 7d4d43d727..e74d5323c8 100644
--- a/tools/qmlprofiler/commandlistener.h
+++ b/tools/qmlprofiler/commandlistener.h
@@ -36,20 +36,13 @@
#include <QtCore/QThread>
-class CommandListener : public QThread
-{
+class CommandListener : public QObject {
Q_OBJECT
-public:
- CommandListener(QObject *parent = 0);
+public slots:
+ void readCommand();
- void run();
-
- void requestStop() { m_stopRequested = true; }
signals:
void command(const QString &command);
-
-private:
- bool m_stopRequested;
};
#endif // COMMANDLISTENER_H
diff --git a/tools/qmlprofiler/constants.h b/tools/qmlprofiler/constants.h
index 4e5aac7e32..5b4b52515f 100644
--- a/tools/qmlprofiler/constants.h
+++ b/tools/qmlprofiler/constants.h
@@ -36,16 +36,27 @@
namespace Constants {
-const char CMD_HELP[] ="help";
-const char CMD_HELP2[] = "h";
-const char CMD_HELP3[] = "?";
-
const char CMD_RECORD[] ="record";
const char CMD_RECORD2[] ="r";
+const char CMD_OUTPUT[] = "output";
+const char CMD_OUTPUT2[] = "o";
+
+const char CMD_FLUSH[] = "flush";
+const char CMD_FLUSH2[] = "f";
+
+const char CMD_CLEAR[] = "clear";
+const char CMD_CLEAR2[] = "c";
+
const char CMD_QUIT[] ="quit";
const char CMD_QUIT2[] = "q";
+const char CMD_YES[] = "yes";
+const char CMD_YES2[] = "y";
+
+const char CMD_NO[] = "no";
+const char CMD_NO2[] = "n";
+
} // Constants
#endif // CONSTANTS_H
diff --git a/tools/qmlprofiler/main.cpp b/tools/qmlprofiler/main.cpp
index a1bd1b38b4..12fcc79efa 100644
--- a/tools/qmlprofiler/main.cpp
+++ b/tools/qmlprofiler/main.cpp
@@ -38,19 +38,23 @@ int main(int argc, char *argv[])
{
QmlProfilerApplication app(argc, argv);
- if (!app.parseArguments()) {
- app.printUsage();
- return 1;
- }
-
- CommandListener listener;
- QObject::connect(&listener, SIGNAL(command(QString)), &app, SLOT(userCommand(QString)));
- listener.start();
-
- int exitValue = app.exec();
- // wait for listener to exit
- listener.wait();
+ app.parseArguments();
-
- return exitValue;
+ if (app.isInteractive()) {
+ QThread listenerThread;
+ CommandListener listener;
+ listener.moveToThread(&listenerThread);
+ QObject::connect(&listener, SIGNAL(command(QString)), &app, SLOT(userCommand(QString)));
+ QObject::connect(&app, SIGNAL(readyForCommand()), &listener, SLOT(readCommand()));
+ listenerThread.start();
+ int exitValue = app.exec();
+ listenerThread.quit();
+ // wait for listener to exit
+ listenerThread.wait();
+ return exitValue;
+ } else {
+ int exitValue = app.exec();
+ app.outputData();
+ return exitValue;
+ }
}
diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp
index a51f67164f..8633810790 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.cpp
+++ b/tools/qmlprofiler/qmlprofilerapplication.cpp
@@ -40,47 +40,49 @@
#include <QtCore/QDateTime>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
-
-static const char usageTextC[] =
-"Usage:\n"
-" qmlprofiler [options] [program] [program-options]\n"
-" qmlprofiler [options] -attach [hostname]\n"
-"\n"
-"QML Profiler retrieves QML tracing data from a running application.\n"
-"The data collected can then be visualized in Qt Creator.\n"
-"\n"
-"The application to be profiled has to enable QML debugging. See the Qt Creator\n"
-"documentation on how to do this for different Qt versions.\n"
-"\n"
-"Options:\n"
-" -help Show this information and exit.\n"
-" -fromStart\n"
-" Record as soon as the engine is started, default is false.\n"
-" -p <number>, -port <number>\n"
-" TCP/IP port to use, default is 3768.\n"
-" -v, -verbose\n"
-" Print debugging output.\n"
-" -version\n"
-" Show the version of qmlprofiler and exit.\n";
+#include <QtCore/QCommandLineParser>
static const char commandTextC[] =
-"Commands:\n"
-" r, record\n"
-" Switch recording on or off.\n"
-" q, quit\n"
-" Terminate program.";
-
-static const char TraceFileExtension[] = ".qtd";
+ "The following commands are available:\n"
+ "'r', 'record'\n"
+ " Switch recording on or off.\n"
+ "'o [file]', 'output [file]'\n"
+ " Output profiling data to <file>. If no <file>\n"
+ " parameter is given, output to whatever was given\n"
+ " with --output, or standard output.\n"
+ "'c', 'clear'\n"
+ " Clear profiling data recorded so far from memory.\n"
+ "'f [file]', 'flush [file]'\n"
+ " Stop recording if it is running, then output the\n"
+ " data, and finally clear it from memory.\n"
+ "'q', 'quit'\n"
+ " Terminate the program if started from qmlprofiler,\n"
+ " and qmlprofiler itself.";
+
+static const char *features[] = {
+ "javascript",
+ "memory",
+ "pixmapcache",
+ "scenegraph",
+ "animations",
+ "painting",
+ "compiling",
+ "creating",
+ "binding",
+ "handlingsignal",
+ "inputevents"
+};
QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) :
QCoreApplication(argc, argv),
m_runMode(LaunchMode),
m_process(0),
- m_tracePrefix(QLatin1String("trace")),
m_hostName(QLatin1String("127.0.0.1")),
m_port(3768),
+ m_pendingRequest(REQUEST_NONE),
m_verbose(false),
- m_quitAfterSave(false),
+ m_recording(true),
+ m_interactive(false),
m_qmlProfilerClient(&m_connection),
m_v8profilerClient(&m_connection),
m_connectionAttempts(0),
@@ -95,11 +97,11 @@ QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) :
connect(&m_connection, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionError(QAbstractSocket::SocketError)));
connect(&m_qmlProfilerClient, SIGNAL(enabledChanged()), this, SLOT(traceClientEnabled()));
- connect(&m_qmlProfilerClient, SIGNAL(recordingChanged(bool)), this, SLOT(recordingChanged()));
connect(&m_qmlProfilerClient, SIGNAL(range(QQmlProfilerService::RangeType,QQmlProfilerService::BindingType,qint64,qint64,QStringList,QmlEventLocation)),
&m_profilerData, SLOT(addQmlEvent(QQmlProfilerService::RangeType,QQmlProfilerService::BindingType,qint64,qint64,QStringList,QmlEventLocation)));
connect(&m_qmlProfilerClient, SIGNAL(traceFinished(qint64)), &m_profilerData, SLOT(setTraceEndTime(qint64)));
connect(&m_qmlProfilerClient, SIGNAL(traceStarted(qint64)), &m_profilerData, SLOT(setTraceStartTime(qint64)));
+ connect(&m_qmlProfilerClient, SIGNAL(traceStarted(qint64)), this, SLOT(notifyTraceStarted()));
connect(&m_qmlProfilerClient, SIGNAL(frame(qint64,int,int,int)), &m_profilerData, SLOT(addFrameEvent(qint64,int,int,int)));
connect(&m_qmlProfilerClient, SIGNAL(sceneGraphFrame(QQmlProfilerService::SceneGraphFrameType,
qint64,qint64,qint64,qint64,qint64,qint64)),
@@ -113,6 +115,8 @@ QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) :
qint64)),
&m_profilerData, SLOT(addMemoryEvent(QQmlProfilerService::MemoryType,qint64,
qint64)));
+ connect(&m_qmlProfilerClient, SIGNAL(inputEvent(QQmlProfilerService::EventType,qint64)),
+ &m_profilerData, SLOT(addInputEvent(QQmlProfilerService::EventType,qint64)));
connect(&m_qmlProfilerClient, SIGNAL(complete()), this, SLOT(qmlComplete()));
@@ -140,63 +144,139 @@ QmlProfilerApplication::~QmlProfilerApplication()
delete m_process;
}
-bool QmlProfilerApplication::parseArguments()
+void QmlProfilerApplication::parseArguments()
{
- for (int argPos = 1; argPos < arguments().size(); ++argPos) {
- const QString arg = arguments().at(argPos);
- if (arg == QLatin1String("-attach") || arg == QLatin1String("-a")) {
- if (argPos + 1 == arguments().size()) {
- return false;
- }
- m_hostName = arguments().at(++argPos);
- m_runMode = AttachMode;
- } else if (arg == QLatin1String("-port") || arg == QLatin1String("-p")) {
- if (argPos + 1 == arguments().size()) {
- return false;
- }
- const QString portStr = arguments().at(++argPos);
- bool isNumber;
- m_port = portStr.toUShort(&isNumber);
- if (!isNumber) {
- logError(QString("'%1' is not a valid port").arg(portStr));
- return false;
- }
- } else if (arg == QLatin1String("-fromStart")) {
- m_qmlProfilerClient.setRecording(true);
- m_v8profilerClient.setRecording(true);
- } else if (arg == QLatin1String("-help") || arg == QLatin1String("-h") || arg == QLatin1String("/h") || arg == QLatin1String("/?")) {
- return false;
- } else if (arg == QLatin1String("-verbose") || arg == QLatin1String("-v")) {
- m_verbose = true;
- } else if (arg == QLatin1String("-version")) {
- print(QString("QML Profiler based on Qt %1.").arg(qVersion()));
- ::exit(1);
- return false;
- } else {
- if (m_programPath.isEmpty()) {
- m_programPath = arg;
- m_tracePrefix = QFileInfo(m_programPath).fileName();
- } else {
- m_programArguments << arg;
- }
+ setApplicationName(QLatin1String("qmlprofiler"));
+ setApplicationVersion(QLatin1String(qVersion()));
+
+ QCommandLineParser parser;
+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+ parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments);
+
+ parser.setApplicationDescription(QChar::LineFeed + tr(
+ "The QML Profiler retrieves QML tracing data from an application. The data\n"
+ "collected can then be visualized in Qt Creator. The application to be profiled\n"
+ "has to enable QML debugging. See the Qt Creator documentation on how to do\n"
+ "this for different Qt versions."));
+
+ QCommandLineOption attach(QStringList() << QLatin1String("a") << QLatin1String("attach"),
+ tr("Attach to an application already running on <hostname>, "
+ "instead of starting it locally."),
+ QLatin1String("hostname"));
+ parser.addOption(attach);
+
+ QCommandLineOption port(QStringList() << QLatin1String("p") << QLatin1String("port"),
+ tr("Connect to the TCP port <port>. The default is 3768."),
+ QLatin1String("port"), QLatin1String("3768"));
+ parser.addOption(port);
+
+ QCommandLineOption output(QStringList() << QLatin1String("o") << QLatin1String("output"),
+ tr("Save tracing data in <file>. By default the data is sent to the "
+ "standard output."), QLatin1String("file"), QString());
+ parser.addOption(output);
+
+ QCommandLineOption record(QLatin1String("record"),
+ tr("If set to 'off', don't immediately start recording data when the "
+ "QML engine starts, but instead either start the recording "
+ "interactively or with the JavaScript console.profile() function. "
+ "By default the recording starts immediately."),
+ QLatin1String("on|off"), QLatin1String("on"));
+ parser.addOption(record);
+
+ QStringList featureList;
+ for (int i = 0; i < QQmlProfilerService::MaximumProfileFeature; ++i)
+ featureList << QLatin1String(features[i]);
+
+ QCommandLineOption include(QLatin1String("include"),
+ tr("Comma-separated list of features to record. By default all "
+ "features supported by the QML engine are recorded. If --include "
+ "is specified, only the given features will be recorded. "
+ "The following features are unserstood by qmlprofiler: %1").arg(
+ featureList.join(", ")),
+ QLatin1String("feature,..."));
+ parser.addOption(include);
+
+ QCommandLineOption exclude(QLatin1String("exclude"),
+ tr("Comma-separated list of features to exclude when recording. By "
+ "default all features supported by the QML engine are recorded. "
+ "See --include for the features understood by qmlprofiler."),
+ QLatin1String("feature,..."));
+ parser.addOption(exclude);
+
+ QCommandLineOption interactive(QLatin1String("interactive"),
+ tr("Manually control the recording from the command line. The "
+ "profiler will not terminate itself when the application "
+ "does so in this case.") + QChar::Space + tr(commandTextC));
+ parser.addOption(interactive);
+
+ QCommandLineOption verbose(QStringList() << QLatin1String("verbose"),
+ tr("Print debugging output."));
+ parser.addOption(verbose);
+
+ parser.addHelpOption();
+ parser.addVersionOption();
+
+ parser.addPositionalArgument(QLatin1String("program"),
+ tr("The program to be started and profiled."),
+ QLatin1String("[program]"));
+ parser.addPositionalArgument(QLatin1String("parameters"),
+ tr("Parameters for the program to be started."),
+ QLatin1String("[parameters...]"));
+
+ parser.process(*this);
+
+ if (parser.isSet(attach)) {
+ m_hostName = parser.value(attach);
+ m_runMode = AttachMode;
+ }
+
+ if (parser.isSet(port)) {
+ bool isNumber;
+ m_port = parser.value(port).toUShort(&isNumber);
+ if (!isNumber) {
+ logError(tr("'%1' is not a valid port.").arg(parser.value(port)));
+ parser.showHelp(1);
}
}
- if (m_runMode == LaunchMode
- && m_programPath.isEmpty())
- return false;
+ m_outputFile = parser.value(output);
- if (m_runMode == AttachMode
- && !m_programPath.isEmpty())
- return false;
+ m_recording = (parser.value(record) == QLatin1String("on"));
+ m_interactive = parser.isSet(interactive);
- return true;
-}
+ quint64 features = std::numeric_limits<quint64>::max();
+ if (parser.isSet(include)) {
+ if (parser.isSet(exclude)) {
+ logError(tr("qmlprofiler can only process either --include or --exclude, not both."));
+ parser.showHelp(4);
+ }
+ features = parseFeatures(featureList, parser.value(include), false);
+ }
-void QmlProfilerApplication::printUsage()
-{
- print(QLatin1String(usageTextC));
- print(QLatin1String(commandTextC));
+ if (parser.isSet(exclude))
+ features = parseFeatures(featureList, parser.value(exclude), true);
+
+ if (features == 0)
+ parser.showHelp(4);
+
+ m_qmlProfilerClient.setFeatures(features);
+
+ if (parser.isSet(verbose))
+ m_verbose = true;
+
+ m_programArguments = parser.positionalArguments();
+ if (!m_programArguments.isEmpty())
+ m_programPath = m_programArguments.takeFirst();
+
+ if (m_runMode == LaunchMode && m_programPath.isEmpty()) {
+ logError(tr("You have to specify either --attach or a program to start."));
+ parser.showHelp(2);
+ }
+
+ if (m_runMode == AttachMode && !m_programPath.isEmpty()) {
+ logError(tr("--attach cannot be used when starting a program."));
+ parser.showHelp(3);
+ }
}
int QmlProfilerApplication::exec()
@@ -205,55 +285,189 @@ int QmlProfilerApplication::exec()
return QCoreApplication::exec();
}
-void QmlProfilerApplication::printCommands()
+bool QmlProfilerApplication::isInteractive() const
+{
+ return m_interactive;
+}
+
+quint64 QmlProfilerApplication::parseFeatures(const QStringList &featureList, const QString &values,
+ bool exclude)
+{
+ quint64 features = exclude ? std::numeric_limits<quint64>::max() : 0;
+ QStringList givenFeatures = values.split(QLatin1Char(','));
+ foreach (const QString &f, givenFeatures) {
+ int index = featureList.indexOf(f);
+ if (index < 0) {
+ logError(tr("Unknown feature '%1'").arg(f));
+ return 0;
+ }
+ quint64 flag = static_cast<quint64>(1) << index;
+ features = (exclude ? (features ^ flag) : (features | flag));
+ }
+ if (features == 0) {
+ logError(exclude ? tr("No features remaining to record after processing --exclude.") :
+ tr("No features specified for --include."));
+ }
+ return features;
+}
+
+void QmlProfilerApplication::flush()
{
- print(QLatin1String(commandTextC));
+ if (m_recording) {
+ m_pendingRequest = REQUEST_FLUSH;
+ m_qmlProfilerClient.sendRecordingStatus(false);
+ m_v8profilerClient.sendRecordingStatus(false);
+ } else {
+ if (m_profilerData.save(m_interactiveOutputFile)) {
+ m_profilerData.clear();
+ if (!m_interactiveOutputFile.isEmpty())
+ prompt(tr("Data written to %1.").arg(m_interactiveOutputFile));
+ else
+ prompt();
+ } else {
+ prompt(tr("Saving failed."));
+ }
+ m_interactiveOutputFile.clear();
+ m_pendingRequest = REQUEST_NONE;
+ }
}
-QString QmlProfilerApplication::traceFileName() const
+void QmlProfilerApplication::output()
{
- QString fileName = m_tracePrefix + "_" +
- QDateTime::currentDateTime().toString(QLatin1String("yyMMdd_hhmmss")) +
- TraceFileExtension;
- if (QFileInfo(fileName).exists()) {
- QString baseName;
- int suffixIndex = 0;
- do {
- baseName = QFileInfo(fileName).baseName()
- + QString::number(suffixIndex++);
- } while (QFileInfo(baseName + TraceFileExtension).exists());
- fileName = baseName + TraceFileExtension;
+ if (m_profilerData.save(m_interactiveOutputFile)) {
+ if (!m_interactiveOutputFile.isEmpty())
+ prompt(tr("Data written to %1.").arg(m_interactiveOutputFile));
+ else
+ prompt();
+ } else {
+ prompt(tr("Saving failed"));
}
- return QFileInfo(fileName).absoluteFilePath();
+ m_interactiveOutputFile.clear();
+ m_pendingRequest = REQUEST_NONE;
+}
+
+bool QmlProfilerApplication::checkOutputFile(PendingRequest pending)
+{
+ if (m_interactiveOutputFile.isEmpty())
+ return true;
+ QFileInfo file(m_interactiveOutputFile);
+ if (file.exists()) {
+ if (!file.isFile()) {
+ prompt(tr("Cannot overwrite %1.").arg(m_interactiveOutputFile));
+ m_interactiveOutputFile.clear();
+ } else {
+ prompt(tr("%1 exists. Overwrite (y/n)?").arg(m_interactiveOutputFile));
+ m_pendingRequest = pending;
+ }
+ return false;
+ } else {
+ return true;
+ }
}
void QmlProfilerApplication::userCommand(const QString &command)
{
- QString cmd = command.trimmed();
- if (cmd == Constants::CMD_HELP
- || cmd == Constants::CMD_HELP2
- || cmd == Constants::CMD_HELP3) {
- printCommands();
- } else if (cmd == Constants::CMD_RECORD
- || cmd == Constants::CMD_RECORD2) {
- m_qmlProfilerClient.setRecording(
- !m_qmlProfilerClient.isRecording());
- m_v8profilerClient.setRecording(!m_v8profilerClient.isRecording());
- m_qmlDataReady = false;
- m_v8DataReady = false;
- } else if (cmd == Constants::CMD_QUIT
- || cmd == Constants::CMD_QUIT2) {
- print(QLatin1String("Quit"));
- if (m_qmlProfilerClient.isRecording()) {
- m_quitAfterSave = true;
- m_qmlDataReady = false;
- m_v8DataReady = false;
- m_qmlProfilerClient.setRecording(false);
- m_v8profilerClient.setRecording(false);
+ QStringList args = command.split(QChar::Space, QString::SkipEmptyParts);
+ if (args.isEmpty()) {
+ prompt();
+ return;
+ }
+
+ QByteArray cmd = args.takeFirst().trimmed().toLatin1();
+
+ if (m_pendingRequest == REQUEST_QUIT) {
+ if (cmd == Constants::CMD_YES || cmd == Constants::CMD_YES2) {
+ quit();
+ } else if (cmd == Constants::CMD_NO || cmd == Constants::CMD_NO2) {
+ m_pendingRequest = REQUEST_NONE;
+ prompt();
+ } else {
+ prompt(tr("The application is still generating data. Really quit (y/n)?"));
+ }
+ return;
+ }
+
+ if (m_pendingRequest == REQUEST_OUTPUT_FILE || m_pendingRequest == REQUEST_FLUSH_FILE) {
+ if (cmd == Constants::CMD_YES || cmd == Constants::CMD_YES2) {
+ if (m_pendingRequest == REQUEST_OUTPUT_FILE)
+ output();
+ else
+ flush();
+ } else if (cmd == Constants::CMD_NO || cmd == Constants::CMD_NO2) {
+ m_pendingRequest = REQUEST_NONE;
+ m_interactiveOutputFile.clear();
+ prompt();
+ } else {
+ prompt(tr("%1 exists. Overwrite (y/n)?"));
+ }
+ return;
+ }
+
+ if (cmd == Constants::CMD_RECORD || cmd == Constants::CMD_RECORD2) {
+ m_pendingRequest = REQUEST_TOGGLE_RECORDING;
+ m_qmlProfilerClient.sendRecordingStatus(!m_recording);
+ m_v8profilerClient.sendRecordingStatus(!m_recording);
+ } else if (cmd == Constants::CMD_QUIT || cmd == Constants::CMD_QUIT2) {
+ m_pendingRequest = REQUEST_QUIT;
+ if (m_recording) {
+ prompt(tr("The application is still generating data. Really quit (y/n)?"));
+ } else if (!m_profilerData.isEmpty()) {
+ prompt(tr("There is still trace data in memory. Really quit (y/n)?"));
} else {
quit();
}
+ } else if (cmd == Constants::CMD_OUTPUT || cmd == Constants::CMD_OUTPUT2) {
+ if (m_recording) {
+ prompt(tr("Cannot output while recording data."));
+ } else if (m_profilerData.isEmpty()) {
+ prompt(tr("No data was recorded so far."));
+ } else {
+ m_interactiveOutputFile = args.length() > 0 ? args[0] : m_outputFile;
+ if (checkOutputFile(REQUEST_OUTPUT_FILE))
+ output();
+ }
+ } else if (cmd == Constants::CMD_CLEAR || cmd == Constants::CMD_CLEAR2) {
+ if (m_recording) {
+ prompt(tr("Cannot clear data while recording."));
+ } else if (m_profilerData.isEmpty()) {
+ prompt(tr("No data was recorded so far."));
+ } else {
+ m_profilerData.clear();
+ prompt(tr("Trace data cleared."));
+ }
+ } else if (cmd == Constants::CMD_FLUSH || cmd == Constants::CMD_FLUSH2) {
+ if (!m_recording && m_profilerData.isEmpty()) {
+ prompt(tr("No data was recorded so far."));
+ } else {
+ m_interactiveOutputFile = args.length() > 0 ? args[0] : m_outputFile;
+ if (checkOutputFile(REQUEST_FLUSH_FILE))
+ flush();
+ }
+ } else {
+ prompt(tr(commandTextC));
+ }
+}
+
+void QmlProfilerApplication::notifyTraceStarted()
+{
+ // Synchronize to server state. It doesn't hurt to do this multiple times in a row for
+ // different traces. There is no symmetric event to "Complete" after all.
+ m_recording = true;
+
+ if (m_pendingRequest == REQUEST_TOGGLE_RECORDING) {
+ m_pendingRequest = REQUEST_NONE;
+ prompt(tr("Recording started"));
+ } else {
+ prompt(tr("Application started recording"), false);
+ }
+}
+
+void QmlProfilerApplication::outputData()
+{
+ if (!m_profilerData.isEmpty()) {
+ m_profilerData.save(m_outputFile);
+ m_profilerData.clear();
}
}
@@ -304,17 +518,9 @@ void QmlProfilerApplication::tryToConnect()
void QmlProfilerApplication::connected()
{
m_connectTimer.stop();
- print(QString(QLatin1String("Connected to host:port %1:%2."
- "Wait for profile data or type a command"
- "(type 'help'' to show list of commands).")
- ).arg(m_hostName).arg((m_port)));
- QString recordingStatus(QLatin1String("Recording Status: %1"));
- if (!m_qmlProfilerClient.isRecording() &&
- !m_v8profilerClient.isRecording())
- recordingStatus = recordingStatus.arg(QLatin1String("Off"));
- else
- recordingStatus = recordingStatus.arg(QLatin1String("On"));
- print(recordingStatus);
+ prompt(tr("Connected to host:port %1:%2. Wait for profile data or type a command (type 'help' "
+ "to show list of commands).\nRecording Status: %3")
+ .arg(m_hostName).arg((m_port)).arg(m_recording ? tr("on") : tr("off")));
}
void QmlProfilerApplication::connectionStateChanged(
@@ -334,7 +540,7 @@ void QmlProfilerApplication::processHasOutput()
{
Q_ASSERT(m_process);
while (m_process->bytesAvailable()) {
- QTextStream out(stdout);
+ QTextStream out(stderr);
out << m_process->readAll();
}
}
@@ -342,19 +548,19 @@ void QmlProfilerApplication::processHasOutput()
void QmlProfilerApplication::processFinished()
{
Q_ASSERT(m_process);
+ int exitCode = 0;
if (m_process->exitStatus() == QProcess::NormalExit) {
logStatus(QString("Process exited (%1).").arg(m_process->exitCode()));
-
- if (m_qmlProfilerClient.isRecording()) {
- logError("Process exited while recording, last trace is lost!");
- exit(2);
- } else {
- exit(0);
+ if (m_recording) {
+ logError("Process exited while recording, last trace is damaged!");
+ exitCode = 2;
}
} else {
- logError("Process crashed! Exiting ...");
- exit(3);
+ logError("Process crashed!");
+ exitCode = 3;
}
+ if (!m_interactive)
+ exit(exitCode);
}
void QmlProfilerApplication::traceClientEnabled()
@@ -362,8 +568,8 @@ void QmlProfilerApplication::traceClientEnabled()
logStatus("Trace client is attached.");
// blocked server is waiting for recording message from both clients
// once the last one is connected, both messages should be sent
- m_qmlProfilerClient.sendRecordingStatus();
- m_v8profilerClient.sendRecordingStatus();
+ m_qmlProfilerClient.sendRecordingStatus(m_recording);
+ m_v8profilerClient.sendRecordingStatus(m_recording);
}
void QmlProfilerApplication::profilerClientEnabled()
@@ -372,34 +578,38 @@ void QmlProfilerApplication::profilerClientEnabled()
// blocked server is waiting for recording message from both clients
// once the last one is connected, both messages should be sent
- m_qmlProfilerClient.sendRecordingStatus();
- m_v8profilerClient.sendRecordingStatus();
+ m_qmlProfilerClient.sendRecordingStatus(m_recording);
+ m_v8profilerClient.sendRecordingStatus(m_recording);
}
void QmlProfilerApplication::traceFinished()
{
- const QString fileName = traceFileName();
+ m_recording = false; // only on "Complete" we know that the trace is really finished.
- if (m_profilerData.save(fileName))
- print(QString("Saving trace to %1.").arg(fileName));
+ // after receiving both notifications, reset the flags
+ m_qmlDataReady = false;
+ m_v8DataReady = false;
- if (m_quitAfterSave)
- quit();
-}
-
-void QmlProfilerApplication::recordingChanged()
-{
- if (m_qmlProfilerClient.isRecording()) {
- print(QLatin1String("Recording is on."));
+ if (m_pendingRequest == REQUEST_FLUSH) {
+ flush();
+ } else if (m_pendingRequest == REQUEST_TOGGLE_RECORDING) {
+ m_pendingRequest = REQUEST_NONE;
+ prompt(tr("Recording stopped."));
} else {
- print(QLatin1String("Recording is off."));
+ prompt(tr("Application stopped recording."), false);
}
}
-void QmlProfilerApplication::print(const QString &line)
+void QmlProfilerApplication::prompt(const QString &line, bool ready)
{
- QTextStream err(stderr);
- err << line << endl;
+ if (m_interactive) {
+ QTextStream err(stderr);
+ if (!line.isEmpty())
+ err << line << endl;
+ err << QLatin1String("> ");
+ if (ready)
+ emit readyForCommand();
+ }
}
void QmlProfilerApplication::logError(const QString &error)
@@ -422,8 +632,6 @@ void QmlProfilerApplication::qmlComplete()
if (m_v8profilerClient.state() != QQmlDebugClient::Enabled ||
m_v8DataReady) {
m_profilerData.complete();
- // once complete is sent, reset the flag
- m_qmlDataReady = false;
}
}
@@ -433,7 +641,5 @@ void QmlProfilerApplication::v8Complete()
if (m_qmlProfilerClient.state() != QQmlDebugClient::Enabled ||
m_qmlDataReady) {
m_profilerData.complete();
- // once complete is sent, reset the flag
- m_v8DataReady = false;
}
}
diff --git a/tools/qmlprofiler/qmlprofilerapplication.h b/tools/qmlprofiler/qmlprofilerapplication.h
index 7e7cebfcf1..f1bf6c3e93 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.h
+++ b/tools/qmlprofiler/qmlprofilerapplication.h
@@ -41,6 +41,15 @@
#include "qmlprofilerclient.h"
#include "qmlprofilerdata.h"
+enum PendingRequest {
+ REQUEST_QUIT,
+ REQUEST_FLUSH_FILE,
+ REQUEST_FLUSH,
+ REQUEST_OUTPUT_FILE,
+ REQUEST_TOGGLE_RECORDING,
+ REQUEST_NONE
+};
+
class QmlProfilerApplication : public QCoreApplication
{
Q_OBJECT
@@ -48,12 +57,17 @@ public:
QmlProfilerApplication(int &argc, char **argv);
~QmlProfilerApplication();
- bool parseArguments();
- void printUsage();
+ void parseArguments();
int exec();
+ bool isInteractive() const;
+
+signals:
+ void readyForCommand();
public slots:
void userCommand(const QString &command);
+ void notifyTraceStarted();
+ void outputData();
private slots:
void run();
@@ -67,9 +81,8 @@ private slots:
void traceClientEnabled();
void profilerClientEnabled();
void traceFinished();
- void recordingChanged();
- void print(const QString &line);
+ void prompt(const QString &line = QString(), bool ready = true);
void logError(const QString &error);
void logStatus(const QString &status);
@@ -77,8 +90,10 @@ private slots:
void v8Complete();
private:
- void printCommands();
- QString traceFileName() const;
+ quint64 parseFeatures(const QStringList &featureList, const QString &values, bool exclude);
+ bool checkOutputFile(PendingRequest pending);
+ void flush();
+ void output();
enum ApplicationMode {
LaunchMode,
@@ -89,12 +104,16 @@ private:
QString m_programPath;
QStringList m_programArguments;
QProcess *m_process;
- QString m_tracePrefix;
QString m_hostName;
quint16 m_port;
+ QString m_outputFile;
+ QString m_interactiveOutputFile;
+
+ PendingRequest m_pendingRequest;
bool m_verbose;
- bool m_quitAfterSave;
+ bool m_recording;
+ bool m_interactive;
QQmlDebugConnection m_connection;
QmlProfilerClient m_qmlProfilerClient;
diff --git a/tools/qmlprofiler/qmlprofilerclient.cpp b/tools/qmlprofiler/qmlprofilerclient.cpp
index 711ddbd862..4976a5a0d9 100644
--- a/tools/qmlprofiler/qmlprofilerclient.cpp
+++ b/tools/qmlprofiler/qmlprofilerclient.cpp
@@ -39,17 +39,12 @@
ProfilerClient::ProfilerClient(const QString &clientName,
QQmlDebugConnection *client)
: QQmlDebugClient(clientName, client),
- m_recording(false),
m_enabled(false)
{
}
ProfilerClient::~ProfilerClient()
{
- //Disable profiling if started by client
- //Profiling data will be lost!!
- if (isRecording())
- setRecording(false);
}
void ProfilerClient::clearData()
@@ -62,29 +57,6 @@ bool ProfilerClient::isEnabled() const
return m_enabled;
}
-void ProfilerClient::sendRecordingStatus()
-{
-}
-
-bool ProfilerClient::isRecording() const
-{
- return m_recording;
-}
-
-void ProfilerClient::setRecording(bool v)
-{
- if (v == m_recording)
- return;
-
- m_recording = v;
-
- if (state() == Enabled) {
- sendRecordingStatus();
- }
-
- emit recordingChanged(v);
-}
-
void ProfilerClient::stateChanged(State status)
{
if ((m_enabled && status != Enabled) ||
@@ -99,8 +71,7 @@ class QmlProfilerClientPrivate
{
public:
QmlProfilerClientPrivate()
- : inProgressRanges(0)
- , maximumTime(0)
+ : inProgressRanges(0) , features(std::numeric_limits<quint64>::max())
{
::memset(rangeCount, 0,
QQmlProfilerService::MaximumRangeType * sizeof(int));
@@ -112,7 +83,8 @@ public:
QStack<QmlEventLocation> rangeLocations[QQmlProfilerService::MaximumRangeType];
QStack<QQmlProfilerService::BindingType> bindingTypes;
int rangeCount[QQmlProfilerService::MaximumRangeType];
- qint64 maximumTime;
+
+ quint64 features;
};
QmlProfilerClient::QmlProfilerClient(
@@ -127,6 +99,11 @@ QmlProfilerClient::~QmlProfilerClient()
delete d;
}
+void QmlProfilerClient::setFeatures(quint64 features)
+{
+ d->features = features;
+}
+
void QmlProfilerClient::clearData()
{
::memset(d->rangeCount, 0,
@@ -135,19 +112,43 @@ void QmlProfilerClient::clearData()
ProfilerClient::clearData();
}
-void QmlProfilerClient::sendRecordingStatus()
+void QmlProfilerClient::sendRecordingStatus(bool record)
{
QByteArray ba;
QDataStream stream(&ba, QIODevice::WriteOnly);
- stream << isRecording();
+ stream << record << -1 << d->features;
sendMessage(ba);
}
+inline QQmlProfilerService::ProfileFeature featureFromRangeType(
+ QQmlProfilerService::RangeType range)
+{
+ switch (range) {
+ case QQmlProfilerService::Painting:
+ return QQmlProfilerService::ProfilePainting;
+ case QQmlProfilerService::Compiling:
+ return QQmlProfilerService::ProfileCompiling;
+ case QQmlProfilerService::Creating:
+ return QQmlProfilerService::ProfileCreating;
+ case QQmlProfilerService::Binding:
+ return QQmlProfilerService::ProfileBinding;
+ case QQmlProfilerService::HandlingSignal:
+ return QQmlProfilerService::ProfileHandlingSignal;
+ case QQmlProfilerService::Javascript:
+ return QQmlProfilerService::ProfileJavaScript;
+ default:
+ return QQmlProfilerService::MaximumProfileFeature;
+ }
+}
+
void QmlProfilerClient::messageReceived(const QByteArray &data)
{
QByteArray rwData = data;
QDataStream stream(&rwData, QIODevice::ReadOnly);
+ // Force all the 1 << <FLAG> expressions to be done in 64 bit, to silence some warnings
+ const quint64 one = static_cast<quint64>(1);
+
qint64 time;
int messageType;
@@ -162,25 +163,27 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
if (event == QQmlProfilerService::EndTrace) {
emit this->traceFinished(time);
- d->maximumTime = time;
- d->maximumTime = qMax(time, d->maximumTime);
} else if (event == QQmlProfilerService::AnimationFrame) {
+ if (!(d->features & one << QQmlProfilerService::ProfileAnimations))
+ return;
int frameRate, animationCount;
int threadId = 0;
stream >> frameRate >> animationCount;
if (!stream.atEnd())
stream >> threadId;
emit this->frame(time, frameRate, animationCount, threadId);
- d->maximumTime = qMax(time, d->maximumTime);
} else if (event == QQmlProfilerService::StartTrace) {
emit this->traceStarted(time);
- d->maximumTime = time;
- } else if (event < QQmlProfilerService::MaximumEventType) {
- d->maximumTime = qMax(time, d->maximumTime);
+ } else if (event == QQmlProfilerService::Key || event == QQmlProfilerService::Mouse) {
+ if (!(d->features & one << QQmlProfilerService::ProfileInputEvents))
+ return;
+ emit this->inputEvent((QQmlProfilerService::EventType)event, time);
}
} else if (messageType == QQmlProfilerService::Complete) {
emit complete();
} else if (messageType == QQmlProfilerService::SceneGraphFrame) {
+ if (!(d->features & one << QQmlProfilerService::ProfileSceneGraph))
+ return;
int sgEventType;
int count = 0;
qint64 params[5];
@@ -193,8 +196,9 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
params[count++] = 0;
emit sceneGraphFrame((QQmlProfilerService::SceneGraphFrameType)sgEventType, time,
params[0], params[1], params[2], params[3], params[4]);
- d->maximumTime = qMax(time, d->maximumTime);
} else if (messageType == QQmlProfilerService::PixmapCacheEvent) {
+ if (!(d->features & one << QQmlProfilerService::ProfilePixmapCache))
+ return;
int pixEvTy, width = 0, height = 0, refcount = 0;
QString pixUrl;
stream >> pixEvTy >> pixUrl;
@@ -207,13 +211,13 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
}
emit pixmapCache((QQmlProfilerService::PixmapEventType)pixEvTy, time,
QmlEventLocation(pixUrl,0,0), width, height, refcount);
- d->maximumTime = qMax(time, d->maximumTime);
} else if (messageType == QQmlProfilerService::MemoryAllocation) {
+ if (!(d->features & one << QQmlProfilerService::ProfileMemory))
+ return;
int type;
qint64 delta;
stream >> type >> delta;
emit memoryAllocation((QQmlProfilerService::MemoryType)type, time, delta);
- d->maximumTime = qMax(time, d->maximumTime);
} else {
int range;
stream >> range;
@@ -221,6 +225,10 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
if (range >= QQmlProfilerService::MaximumRangeType)
return;
+ if (!(d->features & one << featureFromRangeType(
+ static_cast<QQmlProfilerService::RangeType>(range))))
+ return;
+
if (messageType == QQmlProfilerService::RangeStart) {
d->rangeStartTimes[range].push(time);
d->inProgressRanges |= (static_cast<qint64>(1) << range);
@@ -263,7 +271,6 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
if (d->inProgressRanges & (static_cast<qint64>(1) << range))
d->inProgressRanges &= ~(static_cast<qint64>(1) << range);
- d->maximumTime = qMax(time, d->maximumTime);
QStringList data = d->rangeDatas[range].count() ?
d->rangeDatas[range].pop() : QStringList();
QmlEventLocation location = d->rangeLocations[range].count() ?
@@ -296,19 +303,14 @@ V8ProfilerClient::~V8ProfilerClient()
{
}
-void V8ProfilerClient::sendRecordingStatus()
+void V8ProfilerClient::sendRecordingStatus(bool record)
{
QByteArray ba;
QDataStream stream(&ba, QIODevice::WriteOnly);
QByteArray cmd("V8PROFILER");
- QByteArray option("");
+ QByteArray option(record ? "start" : "stop");
QByteArray title("");
- if (m_recording) {
- option = "start";
- } else {
- option = "stop";
- }
stream << cmd << option << title;
sendMessage(ba);
}
diff --git a/tools/qmlprofiler/qmlprofilerclient.h b/tools/qmlprofiler/qmlprofilerclient.h
index 2d9c382ff6..f41ebbd4c9 100644
--- a/tools/qmlprofiler/qmlprofilerclient.h
+++ b/tools/qmlprofiler/qmlprofilerclient.h
@@ -44,25 +44,18 @@ class ProfilerClient : public QQmlDebugClient
Q_OBJECT
Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged)
- Q_PROPERTY(bool recording READ isRecording WRITE setRecording
- NOTIFY recordingChanged)
-
public:
ProfilerClient(const QString &clientName,
QQmlDebugConnection *client);
~ProfilerClient();
bool isEnabled() const;
- bool isRecording() const;
public slots:
- void setRecording(bool);
virtual void clearData();
- virtual void sendRecordingStatus();
signals:
void complete();
- void recordingChanged(bool arg);
void enabledChanged();
void cleared();
@@ -70,7 +63,6 @@ protected:
virtual void stateChanged(State);
protected:
- bool m_recording;
bool m_enabled;
};
@@ -82,9 +74,11 @@ public:
QmlProfilerClient(QQmlDebugConnection *client);
~QmlProfilerClient();
+ void setFeatures(quint64 features);
+
public slots:
void clearData();
- void sendRecordingStatus();
+ void sendRecordingStatus(bool record);
signals:
void traceFinished( qint64 time );
@@ -101,6 +95,7 @@ signals:
void pixmapCache(QQmlProfilerService::PixmapEventType, qint64 time,
const QmlEventLocation &location, int width, int height, int refCount);
void memoryAllocation(QQmlProfilerService::MemoryType type, qint64 time, qint64 amount);
+ void inputEvent(QQmlProfilerService::EventType, qint64 time);
protected:
virtual void messageReceived(const QByteArray &);
@@ -125,7 +120,7 @@ public:
~V8ProfilerClient();
public slots:
- void sendRecordingStatus();
+ void sendRecordingStatus(bool record);
signals:
void range(int depth, const QString &function, const QString &filename,
diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp
index c5992652f8..347c51c13b 100644
--- a/tools/qmlprofiler/qmlprofilerdata.cpp
+++ b/tools/qmlprofiler/qmlprofilerdata.cpp
@@ -177,18 +177,18 @@ QmlProfilerData::~QmlProfilerData()
void QmlProfilerData::clear()
{
- qDeleteAll(d->eventDescriptions.values());
+ qDeleteAll(d->eventDescriptions);
d->eventDescriptions.clear();
d->startInstanceList.clear();
- qDeleteAll(d->v8EventHash.values());
+ qDeleteAll(d->v8EventHash);
d->v8EventHash.clear();
d->v8parents.clear();
d->clearV8RootEvent();
d->v8MeasuredTime = 0;
- d->traceEndTime = 0;
- d->traceStartTime = -1;
+ d->traceEndTime = std::numeric_limits<qint64>::min();
+ d->traceStartTime = std::numeric_limits<qint64>::max();
d->qmlMeasuredTime = 0;
setState(Empty);
@@ -226,12 +226,14 @@ QString QmlProfilerData::qmlMessageAsString(QQmlProfilerService::Message type)
void QmlProfilerData::setTraceStartTime(qint64 time)
{
- d->traceStartTime = time;
+ if (time < d->traceStartTime)
+ d->traceStartTime = time;
}
void QmlProfilerData::setTraceEndTime(qint64 time)
{
- d->traceEndTime = time;
+ if (time > d->traceEndTime)
+ d->traceEndTime = time;
}
qint64 QmlProfilerData::traceStartTime() const
@@ -388,6 +390,25 @@ void QmlProfilerData::addMemoryEvent(QQmlProfilerService::MemoryType type, qint6
d->startInstanceList.append(rangeEventStartInstance);
}
+void QmlProfilerData::addInputEvent(QQmlProfilerDefinitions::EventType type, qint64 time)
+{
+ setState(AcquiringData);
+
+ QString eventHashStr = QString::fromLatin1("Input:%1").arg(type);
+
+ QmlRangeEventData *newEvent;
+ if (d->eventDescriptions.contains(eventHashStr)) {
+ newEvent = d->eventDescriptions[eventHashStr];
+ } else {
+ newEvent = new QmlRangeEventData(QString(), type, eventHashStr, QmlEventLocation(),
+ QString(), QQmlProfilerService::Event,
+ QQmlProfilerService::MaximumRangeType);
+ d->eventDescriptions.insert(eventHashStr, newEvent);
+ }
+
+ d->startInstanceList.append(QmlRangeEventStartInstance(time, -1, 0, 0, 0, newEvent));
+}
+
QString QmlProfilerData::rootEventName()
{
return tr("<program>");
@@ -551,10 +572,18 @@ bool QmlProfilerData::save(const QString &filename)
return false;
}
- QFile file(filename);
- if (!file.open(QIODevice::WriteOnly)) {
- emit error(tr("Could not open %1 for writing").arg(filename));
- return false;
+ QFile file;
+ if (!filename.isEmpty()) {
+ file.setFileName(filename);
+ if (!file.open(QIODevice::WriteOnly)) {
+ emit error(tr("Could not open %1 for writing").arg(filename));
+ return false;
+ }
+ } else {
+ if (!file.open(stdout, QIODevice::WriteOnly)) {
+ emit error(tr("Could not open stdout for writing"));
+ return false;
+ }
}
QXmlStreamWriter stream(&file);
@@ -589,11 +618,22 @@ bool QmlProfilerData::save(const QString &filename)
if (eventData->rangeType == QQmlProfilerService::Binding)
stream.writeTextElement(QStringLiteral("bindingType"),
QString::number((int)eventData->detailType));
- else if (eventData->message == QQmlProfilerService::Event &&
- eventData->detailType == QQmlProfilerService::AnimationFrame)
- stream.writeTextElement(QStringLiteral("animationFrame"),
- QString::number((int)eventData->detailType));
- else if (eventData->message == QQmlProfilerService::PixmapCacheEvent)
+ else if (eventData->message == QQmlProfilerService::Event) {
+ switch (eventData->detailType) {
+ case QQmlProfilerService::AnimationFrame:
+ stream.writeTextElement(QStringLiteral("animationFrame"),
+ QString::number((int)eventData->detailType));
+ break;
+ case QQmlProfilerService::Key:
+ stream.writeTextElement(QStringLiteral("keyEvent"),
+ QString::number((int)eventData->detailType));
+ break;
+ case QQmlProfilerService::Mouse:
+ stream.writeTextElement(QStringLiteral("mouseEvent"),
+ QString::number((int)eventData->detailType));
+ break;
+ }
+ } else if (eventData->message == QQmlProfilerService::PixmapCacheEvent)
stream.writeTextElement(QStringLiteral("cacheEventType"),
QString::number((int)eventData->detailType));
else if (eventData->message == QQmlProfilerService::SceneGraphFrame)
diff --git a/tools/qmlprofiler/qmlprofilerdata.h b/tools/qmlprofiler/qmlprofilerdata.h
index d420275d5e..ef8ef10929 100644
--- a/tools/qmlprofiler/qmlprofilerdata.h
+++ b/tools/qmlprofiler/qmlprofilerdata.h
@@ -88,6 +88,7 @@ public slots:
void addPixmapCacheEvent(QQmlProfilerService::PixmapEventType type, qint64 time,
const QmlEventLocation &location, int width, int height, int refcount);
void addMemoryEvent(QQmlProfilerService::MemoryType type, qint64 time, qint64 size);
+ void addInputEvent(QQmlProfilerService::EventType type, qint64 time);
void complete();
bool save(const QString &filename);