aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules2
-rw-r--r--.qmake.conf2
-rw-r--r--examples/qml/qmlextensionplugins/plugin.cpp2
-rw-r--r--examples/qml/referenceexamples/binding/happybirthdaysong.cpp2
-rw-r--r--examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp2
-rw-r--r--examples/quick/embeddedinwidgets/main.cpp11
-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/quickwidgets/quickwidget/main.cpp17
-rw-r--r--examples/quick/rendercontrol/window_multithreaded.cpp2
-rw-r--r--examples/quick/rendercontrol/window_singlethreaded.cpp2
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.cpp13
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.h2
-rw-r--r--examples/quick/scenegraph/textureinthread/threadrenderer.cpp10
-rw-r--r--examples/quick/scenegraph/threadedanimation/spinner.cpp4
-rw-r--r--examples/quick/scenegraph/twotextureproviders/xorblender.cpp4
-rw-r--r--examples/quick/shared/shared.h4
-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/FilePrintStream.cpp3
-rw-r--r--src/3rdparty/masm/wtf/Platform.h2
-rw-r--r--src/imports/folderlistmodel/fileinfothread.cpp3
-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/qtquick2/plugins.qmltypes1
-rw-r--r--src/imports/testlib/TestCase.qml16
-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/plugins.pro2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp (renamed from src/qml/debugger/qdebugmessageservice.cpp)62
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h (renamed from src/qml/debugger/qdebugmessageservice_p.h)21
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro32
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp56
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h (renamed from src/qml/jsruntime/qv4qmlextensions.cpp)22
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp (renamed from src/qml/debugger/qqmlenginedebugservice.cpp)130
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h (renamed from src/qml/debugger/qqmlenginedebugservice_p.h)27
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp (renamed from src/qml/qml/qqmlwatcher.cpp)6
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.h (renamed from src/qml/qml/qqmlwatcher_p.h)6
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp480
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h180
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp252
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h97
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp910
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h (renamed from src/qml/debugger/qv4debugservice_p.h)67
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp (renamed from src/plugins/qmltooling/shared/abstracttool.cpp)4
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstracttool.h (renamed from src/plugins/qmltooling/shared/abstracttool.h)3
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp (renamed from src/plugins/qmltooling/shared/abstractviewinspector.cpp)21
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h (renamed from src/plugins/qmltooling/shared/abstractviewinspector.h)12
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/highlight.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp)6
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/highlight.h (renamed from src/plugins/qmltooling/qmldbg_qtquick2/highlight.h)5
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp)13
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/inspecttool.h (renamed from src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h)10
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro27
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp127
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h (renamed from src/qml/debugger/qqmlinspectorinterface_p.h)30
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp)14
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h (renamed from src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h)7
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp157
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h52
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro20
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro28
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp (renamed from src/qml/debugger/qqmlenginecontrolservice.cpp)18
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h (renamed from src/qml/debugger/qqmlenginecontrolservice_p.h)8
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp123
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h (renamed from src/qml/debugger/qqmlconfigurabledebugservice_p_p.h)31
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp (renamed from src/qml/debugger/qqmlprofilerservice.cpp)181
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h (renamed from src/qml/debugger/qqmlprofilerservice_p.h)28
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp51
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h62
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp (renamed from src/qml/debugger/qv4profileradapter.cpp)90
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h (renamed from src/qml/debugger/qv4profileradapter_p.h)15
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro27
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp78
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro22
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp700
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h65
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri14
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro18
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp196
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h52
-rw-r--r--src/plugins/qmltooling/qmltooling.pro10
-rw-r--r--src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h106
-rw-r--r--src/plugins/qmltooling/shared/qqmldebugserver.h62
-rw-r--r--src/plugins/qmltooling/shared/qqmldebugserverconnection.h (renamed from src/qml/debugger/qqmldebugserverconnection_p.h)26
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp28
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h5
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp51
-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/qv4instr_moth_p.h78
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp89
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h7
-rw-r--r--src/qml/compiler/qv4isel_p.cpp42
-rw-r--r--src/qml/compiler/qv4isel_p.h7
-rw-r--r--src/qml/compiler/qv4jsir.cpp18
-rw-r--r--src/qml/compiler/qv4jsir_p.h25
-rw-r--r--src/qml/compiler/qv4ssa.cpp6
-rw-r--r--src/qml/debugger/debugger.pri31
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice.cpp88
-rw-r--r--src/qml/debugger/qqmldebug.cpp120
-rw-r--r--src/qml/debugger/qqmldebug.h2
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp151
-rw-r--r--src/qml/debugger/qqmldebugconnector_p.h (renamed from src/qml/debugger/qqmlinspectorservice_p.h)67
-rw-r--r--src/qml/debugger/qqmldebugpluginmanager_p.h93
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp787
-rw-r--r--src/qml/debugger/qqmldebugserver_p.h104
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp252
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h42
-rw-r--r--src/qml/debugger/qqmldebugservicefactory_p.h (renamed from src/qml/debugger/qqmldebugservice_p_p.h)24
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces.cpp (renamed from src/qml/jsruntime/qv4qmlextensions_p.h)25
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces_p.h133
-rw-r--r--src/qml/debugger/qqmlinspectorservice.cpp181
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp85
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h26
-rw-r--r--src/qml/debugger/qv4debugservice.cpp1265
-rw-r--r--src/qml/jit/qv4assembler.cpp20
-rw-r--r--src/qml/jit/qv4assembler_p.h36
-rw-r--r--src/qml/jit/qv4binop.cpp63
-rw-r--r--src/qml/jit/qv4isel_masm.cpp95
-rw-r--r--src/qml/jit/qv4isel_masm_p.h7
-rw-r--r--src/qml/jit/qv4regalloc.cpp42
-rw-r--r--src/qml/jit/qv4targetplatform_p.h65
-rw-r--r--src/qml/jsapi/qjsengine.cpp13
-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.cpp37
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp19
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h4
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp126
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h16
-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.cpp337
-rw-r--r--src/qml/jsruntime/qv4context_p.h50
-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.cpp594
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h114
-rw-r--r--src/qml/jsruntime/qv4engine.cpp620
-rw-r--r--src/qml/jsruntime/qv4engine_p.h305
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp73
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h22
-rw-r--r--src/qml/jsruntime/qv4function.cpp4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp157
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h59
-rw-r--r--src/qml/jsruntime/qv4global_p.h7
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp76
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4identifiertable_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.cpp6
-rw-r--r--src/qml/jsruntime/qv4managed_p.h121
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp3
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp21
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp149
-rw-r--r--src/qml/jsruntime/qv4object_p.h99
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp41
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h6
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp74
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h4
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp32
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h20
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp18
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h10
-rw-r--r--src/qml/jsruntime/qv4property_p.h13
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp237
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h34
-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.cpp193
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h34
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h105
-rw-r--r--src/qml/jsruntime/qv4script.cpp99
-rw-r--r--src/qml/jsruntime/qv4script_p.h24
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp32
-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.cpp4
-rw-r--r--src/qml/jsruntime/qv4string_p.h14
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp88
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h20
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp33
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h8
-rw-r--r--src/qml/jsruntime/qv4value.cpp78
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h293
-rw-r--r--src/qml/jsruntime/qv4value_p.h441
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp61
-rw-r--r--src/qml/memory/memory.pri14
-rw-r--r--src/qml/memory/qv4heap_p.h129
-rw-r--r--src/qml/memory/qv4mm.cpp (renamed from src/qml/jsruntime/qv4mm.cpp)64
-rw-r--r--src/qml/memory/qv4mm_p.h (renamed from src/qml/jsruntime/qv4mm_p.h)10
-rw-r--r--src/qml/parser/qqmljsmemorypool_p.h22
-rw-r--r--src/qml/qml.pro4
-rw-r--r--src/qml/qml/ftw/ftw.pri2
-rw-r--r--src/qml/qml/ftw/qqmlpool_p.h270
-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.pri4
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp170
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h140
-rw-r--r--src/qml/qml/qqmlabstractexpression.cpp93
-rw-r--r--src/qml/qml/qqmlabstractexpression_p.h116
-rw-r--r--src/qml/qml/qqmlbinding.cpp434
-rw-r--r--src/qml/qml/qqmlbinding_p.h65
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp316
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h78
-rw-r--r--src/qml/qml/qqmlcomponent.cpp115
-rw-r--r--src/qml/qml/qqmlcomponent.h5
-rw-r--r--src/qml/qml/qqmlcomponent_p.h2
-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.cpp181
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h34
-rw-r--r--src/qml/qml/qqmldata_p.h17
-rw-r--r--src/qml/qml/qqmldirparser.cpp30
-rw-r--r--src/qml/qml/qqmlengine.cpp146
-rw-r--r--src/qml/qml/qqmlengine.h4
-rw-r--r--src/qml/qml/qqmlengine_p.h34
-rw-r--r--src/qml/qml/qqmlexpression.cpp34
-rw-r--r--src/qml/qml/qqmlexpression_p.h12
-rw-r--r--src/qml/qml/qqmlglobal.cpp62
-rw-r--r--src/qml/qml/qqmlglobal_p.h20
-rw-r--r--src/qml/qml/qqmlimport.cpp29
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp164
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h101
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp14
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h8
-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.cpp17
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-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.cpp45
-rw-r--r--src/qml/qml/qqmlopenmetaobject_p.h3
-rw-r--r--src/qml/qml/qqmlproperty.cpp456
-rw-r--r--src/qml/qml/qqmlproperty_p.h38
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp25
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h12
-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.cpp955
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h52
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp249
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp59
-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.h27
-rw-r--r--src/qml/types/qqmlbind.cpp90
-rw-r--r--src/qml/types/qqmlconnections.cpp2
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp39
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h2
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h2
-rw-r--r--src/qml/types/qqmllistmodel.cpp190
-rw-r--r--src/qml/types/qqmllistmodel_p.h5
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h77
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp1
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp204
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h15
-rw-r--r--src/qml/types/qquickworkerscript.cpp2
-rw-r--r--src/qml/util/qqmladaptormodel.cpp8
-rw-r--r--src/qmldevtools/qmldevtools.pro1
-rw-r--r--src/qmldevtools/qtqmldevtoolsglobal_p.h17
-rw-r--r--src/qmltest/qmltest.pro4
-rw-r--r--src/qmltest/quicktest.h11
-rw-r--r--src/qmltest/quicktestevent.cpp45
-rw-r--r--src/qmltest/quicktestevent_p.h3
-rw-r--r--src/qmltest/quicktestresult.cpp21
-rw-r--r--src/qmltest/quicktestresult_p.h2
-rw-r--r--src/quick/designer/designer.pri25
-rw-r--r--src/quick/designer/qqmldesignermetaobject.cpp340
-rw-r--r--src/quick/designer/qqmldesignermetaobject_p.h105
-rw-r--r--src/quick/designer/qquickdesignercustomobjectdata.cpp282
-rw-r--r--src/quick/designer/qquickdesignercustomobjectdata_p.h100
-rw-r--r--src/quick/designer/qquickdesignersupport.cpp (renamed from src/quick/designer/designersupport.cpp)96
-rw-r--r--src/quick/designer/qquickdesignersupport_p.h (renamed from src/quick/designer/designersupport.h)22
-rw-r--r--src/quick/designer/qquickdesignersupportitems.cpp320
-rw-r--r--src/quick/designer/qquickdesignersupportitems_p.h (renamed from src/qml/debugger/qqmlconfigurabledebugservice_p.h)50
-rw-r--r--src/quick/designer/qquickdesignersupportmetainfo.cpp (renamed from src/qml/qml/ftw/qqmlpool.cpp)63
-rw-r--r--src/quick/designer/qquickdesignersupportmetainfo_p.h64
-rw-r--r--src/quick/designer/qquickdesignersupportproperties.cpp233
-rw-r--r--src/quick/designer/qquickdesignersupportproperties_p.h98
-rw-r--r--src/quick/designer/qquickdesignersupportpropertychanges.cpp135
-rw-r--r--src/quick/designer/qquickdesignersupportpropertychanges_p.h70
-rw-r--r--src/quick/designer/qquickdesignersupportstates.cpp119
-rw-r--r--src/quick/designer/qquickdesignersupportstates_p.h76
-rw-r--r--src/quick/designer/qquickdesignerwindowmanager.cpp (renamed from src/quick/designer/designerwindowmanager.cpp)25
-rw-r--r--src/quick/designer/qquickdesignerwindowmanager_p.h (renamed from src/quick/designer/designerwindowmanager_p.h)4
-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.cpp28
-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.cpp19
-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.cpp14
-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.cpp124
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h37
-rw-r--r--src/quick/items/qquickitemanimation_p.h2
-rw-r--r--src/quick/items/qquickitemsmodule.cpp21
-rw-r--r--src/quick/items/qquickitemview.cpp112
-rw-r--r--src/quick/items/qquickitemview_p.h9
-rw-r--r--src/quick/items/qquickitemview_p_p.h6
-rw-r--r--src/quick/items/qquickitemviewtransition.cpp1
-rw-r--r--src/quick/items/qquickitemviewtransition_p.h12
-rw-r--r--src/quick/items/qquicklistview.cpp64
-rw-r--r--src/quick/items/qquicklistview_p.h12
-rw-r--r--src/quick/items/qquickloader.cpp7
-rw-r--r--src/quick/items/qquickloader_p.h2
-rw-r--r--src/quick/items/qquickloader_p_p.h3
-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/qquickrectangle_p.h2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp1
-rw-r--r--src/quick/items/qquickrepeater.cpp25
-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.cpp34
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h16
-rw-r--r--src/quick/items/qquickstateoperations.cpp201
-rw-r--r--src/quick/items/qquickstateoperations_p.h8
-rw-r--r--src/quick/items/qquicktext.cpp284
-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.cpp278
-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.cpp447
-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.cpp31
-rw-r--r--src/quick/items/qquickview.h3
-rw-r--r--src/quick/items/qquickwindow.cpp132
-rw-r--r--src/quick/items/qquickwindow.h8
-rw-r--r--src/quick/items/qquickwindow_p.h2
-rw-r--r--src/quick/qtquick2.cpp16
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp47
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h18
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp4
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h2
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp70
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h10
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp11
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer.cpp25
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer_p.h10
-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.cpp64
-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/qquickglobal.cpp269
-rw-r--r--src/quick/util/qquickimageprovider.cpp129
-rw-r--r--src/quick/util/qquickimageprovider.h32
-rw-r--r--src/quick/util/qquickpath_p.h2
-rw-r--r--src/quick/util/qquickpixmapcache.cpp243
-rw-r--r--src/quick/util/qquickprofiler.cpp24
-rw-r--r--src/quick/util/qquickprofiler_p.h2
-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.h (renamed from src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h)64
-rw-r--r--src/quick/util/qquickvaluetypes.cpp10
-rw-r--r--src/quick/util/qquickvaluetypes_p.h8
-rw-r--r--src/quick/util/util.pri6
-rw-r--r--src/quickwidgets/qquickwidget.cpp42
-rw-r--r--src/quickwidgets/qquickwidget.h3
-rw-r--r--src/quickwidgets/qquickwidget_p.h2
-rw-r--r--sync.profile2
-rw-r--r--tests/auto/bic/data/QtQuick.5.0.0.linux-gcc-amd64.txt4
-rw-r--r--tests/auto/bic/data/QtQuick.5.1.0.linux-gcc-amd64.txt4
-rw-r--r--tests/auto/bic/data/QtQuick.5.2.0.linux-gcc-amd64.txt4
-rw-r--r--tests/auto/bic/data/QtQuick.5.3.0.linux-gcc-amd64.txt5
-rw-r--r--tests/auto/bic/data/QtQuick.5.4.0.linux-gcc-amd64.txt5
-rw-r--r--tests/auto/bic/data/QtQuickWidgets.5.3.0.linux-gcc-amd64.txt4
-rw-r--r--tests/auto/bic/data/QtQuickWidgets.5.4.0.linux-gcc-amd64.txt5
-rw-r--r--tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp2
-rw-r--r--tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp86
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/BLACKLIST2
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp6
-rw-r--r--tests/auto/qml/debugger/debugger.pro1
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp2
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp45
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp96
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/qqmldebuglocal.pro16
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp146
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.pro0
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp94
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp42
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp26
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp19
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp45
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml14
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro3
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp116
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.cpp2
-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/debugger/shared/qqmldebugtestservice.cpp8
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.h3
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp22
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp14
-rw-r--r--tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp2
-rw-r--r--tests/auto/qml/qml.pro6
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp38
-rw-r--r--tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp10
-rw-r--r--tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp4
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp16
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp151
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp23
-rw-r--r--tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp2
-rw-r--r--tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp18
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp76
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp4
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp68
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp254
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp10
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp18
-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/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h)57
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp256
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp19
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp22
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp2
-rw-r--r--tests/auto/qml/qqmltimer/tst_qqmltimer.cpp10
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp10
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.reply.body29
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect18
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.body29
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.header2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml200
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml161
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml160
-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.cpp131
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp4
-rw-r--r--tests/auto/qml/qv4debugger/qv4debugger.pro10
-rw-r--r--tests/auto/qml/qv4debugger/tst_qv4debugger.cpp363
-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/plugins/qmltooling/shared/qmlinspectorconstants.h)60
-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/qmltest/window/tst_clickwindow.qml84
-rw-r--r--tests/auto/quick/geometry/tst_geometry.cpp6
-rw-r--r--tests/auto/quick/nokeywords/tst_nokeywords.cpp1
-rw-r--r--tests/auto/quick/qquickanchors/tst_qquickanchors.cpp8
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp52
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp64
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp4
-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.cpp49
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/TestComponent.qml9
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/test.qml39
-rw-r--r--tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro16
-rw-r--r--tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp500
-rw-r--r--tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp8
-rw-r--r--tests/auto/quick/qquickflickable/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickflickable/data/movementSignals.qml26
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp198
-rw-r--r--tests/auto/quick/qquickflipable/tst_qquickflipable.cpp8
-rw-r--r--tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp160
-rw-r--r--tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp28
-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/data/qtbug45640.qml24
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp191
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp81
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp110
-rw-r--r--tests/auto/quick/qquickitem/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp78
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp92
-rw-r--r--tests/auto/quick/qquickitemlayer/data/TextureMirroring.qml159
-rw-r--r--tests/auto/quick/qquickitemlayer/qquickitemlayer.pro3
-rw-r--r--tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp93
-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/data/snapOneItemResize.qml16
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp259
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp30
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp22
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp8
-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.cpp73
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp2
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp23
-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.cpp2060
-rw-r--r--tests/auto/quick/qquickrepeater/data/modelCleared.qml17
-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.cpp122
-rw-r--r--tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp8
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp12
-rw-r--r--tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp8
-rw-r--r--tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.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.cpp256
-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.cpp219
-rw-r--r--tests/auto/quick/qquicktextinput/data/padding.qml12
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp285
-rw-r--r--tests/auto/quick/qquickview/data/error2.qml4
-rw-r--r--tests/auto/quick/qquickview/tst_qquickview.cpp19
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp10
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp132
-rw-r--r--tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp10
-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/auto/quick/touchmouse/tst_touchmouse.cpp6
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp4
-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.cpp5
-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.cpp547
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.h35
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.cpp171
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.h27
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.cpp162
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.h17
670 files changed, 26215 insertions, 15332 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/qml/qmlextensionplugins/plugin.cpp b/examples/qml/qmlextensionplugins/plugin.cpp
index 729c88da73..56057b7f06 100644
--- a/examples/qml/qmlextensionplugins/plugin.cpp
+++ b/examples/qml/qmlextensionplugins/plugin.cpp
@@ -110,7 +110,7 @@ public:
if (++instances == 1) {
if (!timer)
timer = new MinuteTimer(QCoreApplication::instance());
- connect(timer, SIGNAL(timeChanged()), this, SIGNAL(timeChanged()));
+ connect(timer, &MinuteTimer::timeChanged, this, &TimeModel::timeChanged);
timer->start();
}
}
diff --git a/examples/qml/referenceexamples/binding/happybirthdaysong.cpp b/examples/qml/referenceexamples/binding/happybirthdaysong.cpp
index 85a5416190..975f6d409a 100644
--- a/examples/qml/referenceexamples/binding/happybirthdaysong.cpp
+++ b/examples/qml/referenceexamples/binding/happybirthdaysong.cpp
@@ -45,7 +45,7 @@ HappyBirthdaySong::HappyBirthdaySong(QObject *parent)
{
setName(QString());
QTimer *timer = new QTimer(this);
- QObject::connect(timer, SIGNAL(timeout()), this, SLOT(advance()));
+ QObject::connect(timer, &QTimer::timeout, this, &HappyBirthdaySong::advance);
timer->start(1000);
}
diff --git a/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp b/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp
index 7655b3ebc9..96b4abe775 100644
--- a/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp
+++ b/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp
@@ -45,7 +45,7 @@ HappyBirthdaySong::HappyBirthdaySong(QObject *parent)
{
setName(QString());
QTimer *timer = new QTimer(this);
- QObject::connect(timer, SIGNAL(timeout()), this, SLOT(advance()));
+ QObject::connect(timer, &QTimer::timeout, this, &HappyBirthdaySong::advance);
timer->start(1000);
}
diff --git a/examples/quick/embeddedinwidgets/main.cpp b/examples/quick/embeddedinwidgets/main.cpp
index aa6da01bd9..ef404f9fb6 100644
--- a/examples/quick/embeddedinwidgets/main.cpp
+++ b/examples/quick/embeddedinwidgets/main.cpp
@@ -63,10 +63,10 @@ MainWindow::MainWindow()
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
m_quickView->setResizeMode(QQuickView::SizeRootObjectToView);
- connect(m_quickView, SIGNAL(statusChanged(QQuickView::Status)),
- this, SLOT(quickViewStatusChanged(QQuickView::Status)));
- connect(m_quickView, SIGNAL(sceneGraphError(QQuickWindow::SceneGraphError,QString)),
- this, SLOT(sceneGraphError(QQuickWindow::SceneGraphError,QString)));
+ connect(m_quickView, &QQuickView::statusChanged,
+ this, &MainWindow::quickViewStatusChanged);
+ connect(m_quickView, &QQuickWindow::sceneGraphError,
+ this, &MainWindow::sceneGraphError);
m_quickView->setSource(QUrl(QStringLiteral("qrc:///embeddedinwidgets/main.qml")));
QWidget *container = QWidget::createWindowContainer(m_quickView);
@@ -79,8 +79,7 @@ MainWindow::MainWindow()
setCentralWidget(centralWidget);
QMenu *fileMenu = menuBar()->addMenu(tr("File"));
- QAction *quitAction = fileMenu->addAction(tr("Quit"));
- connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ fileMenu->addAction(tr("Quit"), qApp, &QCoreApplication::quit);
}
void MainWindow::quickViewStatusChanged(QQuickView::Status status)
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/quickwidgets/quickwidget/main.cpp b/examples/quick/quickwidgets/quickwidget/main.cpp
index 1e5cf89319..65258d958e 100644
--- a/examples/quick/quickwidgets/quickwidget/main.cpp
+++ b/examples/quick/quickwidgets/quickwidget/main.cpp
@@ -78,10 +78,10 @@ MainWindow::MainWindow()
QUrl source("qrc:quickwidget/rotatingsquare.qml");
- connect(m_quickWidget, SIGNAL(statusChanged(QQuickWidget::Status)),
- this, SLOT(quickWidgetStatusChanged(QQuickWidget::Status)));
- connect(m_quickWidget, SIGNAL(sceneGraphError(QQuickWindow::SceneGraphError,QString)),
- this, SLOT(sceneGraphError(QQuickWindow::SceneGraphError,QString)));
+ connect(m_quickWidget, &QQuickWidget::statusChanged,
+ this, &MainWindow::quickWidgetStatusChanged);
+ connect(m_quickWidget, &QQuickWidget::sceneGraphError,
+ this, &MainWindow::sceneGraphError);
m_quickWidget->resize(300,300);
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView );
m_quickWidget->setSource(source);
@@ -91,12 +91,9 @@ MainWindow::MainWindow()
setCentralWidget(centralWidget);
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
- QAction *grabAction = fileMenu->addAction(tr("Grab to image"));
- connect(grabAction, SIGNAL(triggered()), this, SLOT(grabToFile()));
- QAction *renderAction = fileMenu->addAction(tr("Render to pixmap"));
- connect(renderAction, SIGNAL(triggered()), this, SLOT(renderToFile()));
- QAction *quitAction = fileMenu->addAction(tr("Quit"));
- connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ fileMenu->addAction(tr("Grab to imFage"), this, &MainWindow::grabToFile);
+ fileMenu->addAction(tr("Render to pixmap"), this, &MainWindow::renderToFile);
+ fileMenu->addAction(tr("Quit"), qApp, &QCoreApplication::quit);
}
void MainWindow::quickWidgetStatusChanged(QQuickWidget::Status status)
diff --git a/examples/quick/rendercontrol/window_multithreaded.cpp b/examples/quick/rendercontrol/window_multithreaded.cpp
index 8de5a7776d..4df3488ab3 100644
--- a/examples/quick/rendercontrol/window_multithreaded.cpp
+++ b/examples/quick/rendercontrol/window_multithreaded.cpp
@@ -353,7 +353,7 @@ void WindowMultiThreaded::polishSyncAndRender()
void WindowMultiThreaded::run()
{
- disconnect(m_qmlComponent, SIGNAL(statusChanged(QQmlComponent::Status)), this, SLOT(run()));
+ disconnect(m_qmlComponent, &QQmlComponent::statusChanged, this, &WindowMultiThreaded::run);
if (m_qmlComponent->isError()) {
QList<QQmlError> errorList = m_qmlComponent->errors();
diff --git a/examples/quick/rendercontrol/window_singlethreaded.cpp b/examples/quick/rendercontrol/window_singlethreaded.cpp
index 1e81f08f7e..e43093e241 100644
--- a/examples/quick/rendercontrol/window_singlethreaded.cpp
+++ b/examples/quick/rendercontrol/window_singlethreaded.cpp
@@ -206,7 +206,7 @@ void WindowSingleThreaded::requestUpdate()
void WindowSingleThreaded::run()
{
- disconnect(m_qmlComponent, SIGNAL(statusChanged(QQmlComponent::Status)), this, SLOT(run()));
+ disconnect(m_qmlComponent, &QQmlComponent::statusChanged, this, &WindowSingleThreaded::run);
if (m_qmlComponent->isError()) {
QList<QQmlError> errorList = m_qmlComponent->errors();
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.cpp b/examples/quick/scenegraph/openglunderqml/squircle.cpp
index 8ef975c5b6..8bb9af1ed4 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.cpp
+++ b/examples/quick/scenegraph/openglunderqml/squircle.cpp
@@ -42,7 +42,7 @@ Squircle::Squircle()
: m_t(0)
, m_renderer(0)
{
- connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
+ connect(this, &QQuickItem::windowChanged, this, &Squircle::handleWindowChanged);
}
//! [7]
@@ -62,8 +62,8 @@ void Squircle::setT(qreal t)
void Squircle::handleWindowChanged(QQuickWindow *win)
{
if (win) {
- connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
- connect(win, SIGNAL(sceneGraphInvalidated()), this, SLOT(cleanup()), Qt::DirectConnection);
+ connect(win, &QQuickWindow::beforeSynchronizing, this, &Squircle::sync, Qt::DirectConnection);
+ connect(win, &QQuickWindow::sceneGraphInvalidated, this, &Squircle::cleanup, Qt::DirectConnection);
//! [1]
// If we allow QML to do the clearing, they would clear what we paint
// and nothing would show.
@@ -93,10 +93,11 @@ void Squircle::sync()
{
if (!m_renderer) {
m_renderer = new SquircleRenderer();
- connect(window(), SIGNAL(beforeRendering()), m_renderer, SLOT(paint()), Qt::DirectConnection);
+ connect(window(), &QQuickWindow::beforeRendering, m_renderer, &SquircleRenderer::paint, Qt::DirectConnection);
}
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/examples/quick/scenegraph/textureinthread/threadrenderer.cpp b/examples/quick/scenegraph/textureinthread/threadrenderer.cpp
index 272b903ef2..95fd377dcf 100644
--- a/examples/quick/scenegraph/textureinthread/threadrenderer.cpp
+++ b/examples/quick/scenegraph/textureinthread/threadrenderer.cpp
@@ -228,7 +228,7 @@ void ThreadRenderer::ready()
m_renderThread->moveToThread(m_renderThread);
- connect(window(), SIGNAL(sceneGraphInvalidated()), m_renderThread, SLOT(shutDown()), Qt::QueuedConnection);
+ connect(window(), &QQuickWindow::sceneGraphInvalidated, m_renderThread, &RenderThread::shutDown, Qt::QueuedConnection);
m_renderThread->start();
update();
@@ -274,10 +274,10 @@ QSGNode *ThreadRenderer::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
*
* This FBO rendering pipeline is throttled by vsync on the scene graph rendering thread.
*/
- connect(m_renderThread, SIGNAL(textureReady(int,QSize)), node, SLOT(newTexture(int,QSize)), Qt::DirectConnection);
- connect(node, SIGNAL(pendingNewTexture()), window(), SLOT(update()), Qt::QueuedConnection);
- connect(window(), SIGNAL(beforeRendering()), node, SLOT(prepareNode()), Qt::DirectConnection);
- connect(node, SIGNAL(textureInUse()), m_renderThread, SLOT(renderNext()), Qt::QueuedConnection);
+ connect(m_renderThread, &RenderThread::textureReady, node, &TextureNode::newTexture, Qt::DirectConnection);
+ connect(node, &TextureNode::pendingNewTexture, window(), &QQuickWindow::update, Qt::QueuedConnection);
+ connect(window(), &QQuickWindow::beforeRendering, node, &TextureNode::prepareNode, Qt::DirectConnection);
+ connect(node, &TextureNode::textureInUse, m_renderThread, &RenderThread::renderNext, Qt::QueuedConnection);
// Get the production of FBO textures started..
QMetaObject::invokeMethod(m_renderThread, "renderNext", Qt::QueuedConnection);
diff --git a/examples/quick/scenegraph/threadedanimation/spinner.cpp b/examples/quick/scenegraph/threadedanimation/spinner.cpp
index 04b91e5449..6fefc33f4d 100644
--- a/examples/quick/scenegraph/threadedanimation/spinner.cpp
+++ b/examples/quick/scenegraph/threadedanimation/spinner.cpp
@@ -49,8 +49,8 @@ public:
, m_spinning(false)
, m_window(window)
{
- connect(window, SIGNAL(beforeRendering()), this, SLOT(maybeRotate()));
- connect(window, SIGNAL(frameSwapped()), this, SLOT(maybeUpdate()));
+ connect(window, &QQuickWindow::beforeRendering, this, &SpinnerNode::maybeRotate);
+ connect(window, &QQuickWindow::frameSwapped, this, &SpinnerNode::maybeUpdate);
QImage image(":/scenegraph/threadedanimation/spinner.png");
m_texture = window->createTextureFromImage(image);
diff --git a/examples/quick/scenegraph/twotextureproviders/xorblender.cpp b/examples/quick/scenegraph/twotextureproviders/xorblender.cpp
index 384d118809..0dd035ffea 100644
--- a/examples/quick/scenegraph/twotextureproviders/xorblender.cpp
+++ b/examples/quick/scenegraph/twotextureproviders/xorblender.cpp
@@ -151,8 +151,8 @@ public:
// If this node is used as in a shader effect source, we need to propegate
// changes that will occur in this node outwards.
- connect(m_provider1, SIGNAL(textureChanged()), this, SLOT(textureChange()), Qt::DirectConnection);
- connect(m_provider2, SIGNAL(textureChanged()), this, SLOT(textureChange()), Qt::DirectConnection);
+ connect(m_provider1.data(), &QSGTextureProvider::textureChanged, this, &XorNode::textureChange, Qt::DirectConnection);
+ connect(m_provider2.data(), &QSGTextureProvider::textureChanged, this, &XorNode::textureChange, Qt::DirectConnection);
}
void preprocess() {
diff --git a/examples/quick/shared/shared.h b/examples/quick/shared/shared.h
index 4472b9bfbb..d8fb80b97e 100644
--- a/examples/quick/shared/shared.h
+++ b/examples/quick/shared/shared.h
@@ -55,9 +55,11 @@
f.setVersion(4, 4);\
view.setFormat(f);\
}\
- view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));\
+ view.connect(view.engine(), &QQmlEngine::quit, &app, &QCoreApplication::quit);\
new QQmlFileSelector(view.engine(), &view);\
view.setSource(QUrl("qrc:///" #NAME ".qml")); \
+ if (view.status() == QQuickView::Error)\
+ return -1;\
view.setResizeMode(QQuickView::SizeRootObjectToView);\
if (QGuiApplication::platformName() == QLatin1String("qnx") || \
QGuiApplication::platformName() == QLatin1String("eglfs")) {\
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/FilePrintStream.cpp b/src/3rdparty/masm/wtf/FilePrintStream.cpp
index b5ab25e0bf..45f1565f46 100644
--- a/src/3rdparty/masm/wtf/FilePrintStream.cpp
+++ b/src/3rdparty/masm/wtf/FilePrintStream.cpp
@@ -38,7 +38,8 @@ FilePrintStream::~FilePrintStream()
{
if (m_adoptionMode == Borrow)
return;
- fclose(m_file);
+ if (m_file)
+ fclose(m_file);
}
PassOwnPtr<FilePrintStream> FilePrintStream::open(const char* filename, const char* mode)
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..ebdfba42a8 100644
--- a/src/imports/folderlistmodel/fileinfothread.cpp
+++ b/src/imports/folderlistmodel/fileinfothread.cpp
@@ -251,7 +251,8 @@ void FileInfoThread::getFileInfos(const QString &path)
fileInfoList = currentDir.entryInfoList(nameFilters, filter, sortFlags);
if (!fileInfoList.isEmpty()) {
- foreach (QFileInfo info, fileInfoList) {
+ filePropertyList.reserve(fileInfoList.count());
+ foreach (const 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/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes
index d98e9e6981..050d0f78cd 100644
--- a/src/imports/qtquick2/plugins.qmltypes
+++ b/src/imports/qtquick2/plugins.qmltypes
@@ -1728,6 +1728,7 @@ Module {
}
}
Property { name: "family"; type: "string" }
+ Property { name: "styleName"; type: "string" }
Property { name: "bold"; type: "bool" }
Property { name: "weight"; type: "FontWeight" }
Property { name: "italic"; type: "bool" }
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 039ee63f07..8bedad40e9 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
@@ -869,6 +876,9 @@ Item {
focused item. If \a delay is larger than 0, the test will wait for
\a delay milliseconds.
+ The event will be sent to the TestCase window or, in case of multiple windows,
+ to the current active window. See \l QGuiApplication::focusWindow() for more details.
+
\b{Note:} At some point you should release the key using keyRelease().
\sa keyRelease(), keyClick()
@@ -894,6 +904,9 @@ Item {
focused item. If \a delay is larger than 0, the test will wait for
\a delay milliseconds.
+ The event will be sent to the TestCase window or, in case of multiple windows,
+ to the current active window. See \l QGuiApplication::focusWindow() for more details.
+
\sa keyPress(), keyClick()
*/
function keyRelease(key, modifiers, delay) {
@@ -917,6 +930,9 @@ Item {
focused item. If \a delay is larger than 0, the test will wait for
\a delay milliseconds.
+ The event will be sent to the TestCase window or, in case of multiple windows,
+ to the current active window. See \l QGuiApplication::focusWindow() for more details.
+
\sa keyPress(), keyRelease()
*/
function keyClick(key, modifiers, delay) {
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 7df3299325..d78a350306 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/plugins.pro b/src/plugins/plugins.pro
index 664a457608..273407c19d 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,2 +1,2 @@
TEMPLATE = subdirs
-SUBDIRS += qmltooling
+!contains(QT_CONFIG, no-qml-debug):SUBDIRS += qmltooling
diff --git a/src/qml/debugger/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
index deaa472ce0..6bccec08b1 100644
--- a/src/qml/debugger/qdebugmessageservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
@@ -31,62 +31,37 @@
**
****************************************************************************/
-#include "qdebugmessageservice_p.h"
-#include "qqmldebugservice_p_p.h"
+#include "qdebugmessageservice.h"
+#include <private/qqmldebugconnector_p.h>
#include <QDataStream>
-#include <QMutex>
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QDebugMessageService, qmlDebugMessageService)
+const QString QDebugMessageService::s_key = QStringLiteral("DebugMessages");
void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt,
const QString &buf)
{
- QDebugMessageService::instance()->sendDebugMessage(type, ctxt, buf);
+ QQmlDebugConnector::service<QDebugMessageService>()->sendDebugMessage(type, ctxt, buf);
}
-class QDebugMessageServicePrivate : public QQmlDebugServicePrivate
-{
-public:
- QDebugMessageServicePrivate()
- : oldMsgHandler(0)
- , prevState(QQmlDebugService::NotConnected)
- {
- }
-
- QtMessageHandler oldMsgHandler;
- QQmlDebugService::State prevState;
- QMutex initMutex;
-};
-
QDebugMessageService::QDebugMessageService(QObject *parent) :
- QQmlDebugService(*(new QDebugMessageServicePrivate()),
- QStringLiteral("DebugMessages"), 2, parent)
+ QQmlDebugService(s_key, 2, parent), oldMsgHandler(0),
+ prevState(QQmlDebugService::NotConnected)
{
- Q_D(QDebugMessageService);
-
// don't execute stateChanged() in parallel
- QMutexLocker lock(&d->initMutex);
- registerService();
+ QMutexLocker lock(&initMutex);
if (state() == Enabled) {
- d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
- d->prevState = Enabled;
+ oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
+ prevState = Enabled;
}
}
-QDebugMessageService *QDebugMessageService::instance()
-{
- return qmlDebugMessageService();
-}
-
void QDebugMessageService::sendDebugMessage(QtMsgType type,
const QMessageLogContext &ctxt,
const QString &buf)
{
- Q_D(QDebugMessageService);
-
//We do not want to alter the message handling mechanism
//We just eavesdrop and forward the messages to a port
//only if a client is connected to it.
@@ -96,27 +71,26 @@ void QDebugMessageService::sendDebugMessage(QtMsgType type,
ws << QString::fromLatin1(ctxt.file).toUtf8();
ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8();
- sendMessage(message);
- if (d->oldMsgHandler)
- (*d->oldMsgHandler)(type, ctxt, buf);
+ emit messageToClient(name(), message);
+ if (oldMsgHandler)
+ (*oldMsgHandler)(type, ctxt, buf);
}
void QDebugMessageService::stateChanged(State state)
{
- Q_D(QDebugMessageService);
- QMutexLocker lock(&d->initMutex);
+ QMutexLocker lock(&initMutex);
- if (state != Enabled && d->prevState == Enabled) {
- QtMessageHandler handler = qInstallMessageHandler(d->oldMsgHandler);
+ if (state != Enabled && prevState == Enabled) {
+ QtMessageHandler handler = qInstallMessageHandler(oldMsgHandler);
// has our handler been overwritten in between?
if (handler != DebugMessageHandler)
qInstallMessageHandler(handler);
- } else if (state == Enabled && d->prevState != Enabled) {
- d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
+ } else if (state == Enabled && prevState != Enabled) {
+ oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
}
- d->prevState = state;
+ prevState = state;
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qdebugmessageservice_p.h b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
index 694cd0e64c..c0dc41bcd0 100644
--- a/src/qml/debugger/qdebugmessageservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QDEBUGMESSAGESERVICE_P_H
-#define QDEBUGMESSAGESERVICE_P_H
+#ifndef QDEBUGMESSAGESERVICE_H
+#define QDEBUGMESSAGESERVICE_H
//
// W A R N I N G
@@ -45,9 +45,10 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
+#include <private/qqmldebugservice_p.h>
#include <QtCore/qlogging.h>
+#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -59,19 +60,23 @@ class QDebugMessageService : public QQmlDebugService
public:
QDebugMessageService(QObject *parent = 0);
- static QDebugMessageService *instance();
-
void sendDebugMessage(QtMsgType type, const QMessageLogContext &ctxt,
const QString &buf);
protected:
+ static const QString s_key;
+
void stateChanged(State);
private:
- Q_DISABLE_COPY(QDebugMessageService)
- Q_DECLARE_PRIVATE(QDebugMessageService)
+ friend class QQmlDebugConnector;
+ friend class QQmlDebuggerServiceFactory;
+
+ QtMessageHandler oldMsgHandler;
+ QQmlDebugService::State prevState;
+ QMutex initMutex;
};
QT_END_NAMESPACE
-#endif // QDEBUGMESSAGESERVICE_P_H
+#endif // QDEBUGMESSAGESERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
new file mode 100644
index 0000000000..d860328dc8
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
@@ -0,0 +1,32 @@
+TARGET = qmldbg_debugger
+QT = qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlDebuggerServiceFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qdebugmessageservice.cpp \
+ $$PWD/qqmldebuggerservicefactory.cpp \
+ $$PWD/qqmlenginedebugservice.cpp \
+ $$PWD/qqmlwatcher.cpp \
+ $$PWD/qv4debugservice.cpp \
+ $$PWD/qv4debuggeragent.cpp \
+ $$PWD/qv4datacollector.cpp
+
+HEADERS += \
+ $$PWD/../shared/qqmlconfigurabledebugservice.h \
+ $$PWD/qdebugmessageservice.h \
+ $$PWD/qqmldebuggerservicefactory.h \
+ $$PWD/qqmlenginedebugservice.h \
+ $$PWD/qqmlwatcher.h \
+ $$PWD/qv4debugservice.h \
+ $$PWD/qv4debuggeragent.h \
+ $$PWD/qv4datacollector.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qqmldebuggerservice.json
+
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json
new file mode 100644
index 0000000000..b1e90364d5
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "DebugMessages", "QmlDebugger", "V8Debugger" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
new file mode 100644
index 0000000000..7ba2aeecb0
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** 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 "qqmldebuggerservicefactory.h"
+#include "qqmlenginedebugservice.h"
+#include "qdebugmessageservice.h"
+#include "qv4debugservice.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebugService *QQmlDebuggerServiceFactory::create(const QString &key)
+{
+ if (key == QDebugMessageService::s_key)
+ return new QDebugMessageService(this);
+
+ if (key == QQmlEngineDebugServiceImpl::s_key)
+ return new QQmlEngineDebugServiceImpl(this);
+
+ if (key == QV4DebugServiceImpl::s_key)
+ return new QV4DebugServiceImpl(this);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4qmlextensions.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h
index c1c4e0ec78..2c7509ba12 100644
--- a/src/qml/jsruntime/qv4qmlextensions.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h
@@ -31,13 +31,21 @@
**
****************************************************************************/
-#include "qv4qmlextensions_p.h"
-#include "qv4object_p.h"
+#ifndef QQMLDEBUGGERSERVICEFACTORY_H
+#define QQMLDEBUGGERSERVICEFACTORY_H
-using namespace QV4;
+#include <private/qqmldebugservicefactory_p.h>
-void QmlExtensions::markObjects(ExecutionEngine *e)
+QT_BEGIN_NAMESPACE
+
+class QQmlDebuggerServiceFactory : public QQmlDebugServiceFactory
{
- if (valueTypeWrapperPrototype)
- valueTypeWrapperPrototype->mark(e);
-}
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmldebuggerservice.json")
+public:
+ QQmlDebugService *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGGERSERVICEFACTORY_H
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index da01d00f17..8f53dc6d50 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -31,9 +31,10 @@
**
****************************************************************************/
-#include "qqmlenginedebugservice_p.h"
+#include "qqmlenginedebugservice.h"
+#include "qqmlwatcher.h"
-#include "qqmldebugstatesdelegate_p.h"
+#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlboundsignal_p.h>
#include <qqmlengine.h>
#include <private/qqmlmetatype_p.h>
@@ -41,42 +42,31 @@
#include <private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlcontext_p.h>
-#include <private/qqmlwatcher_p.h>
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlexpression_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
+#include <QtCore/qfileinfo.h>
#include <private/qmetaobject_p.h>
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QQmlEngineDebugService, qmlEngineDebugService)
-
-QQmlEngineDebugService *QQmlEngineDebugService::instance()
-{
- return qmlEngineDebugService();
-}
-
-QQmlEngineDebugService::QQmlEngineDebugService(QObject *parent)
- : QQmlDebugService(QStringLiteral("QmlDebugger"), 2, parent),
- m_watch(new QQmlWatcher(this)),
- m_statesDelegate(0)
+QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) :
+ QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(0)
{
QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
-
- registerService();
}
-QQmlEngineDebugService::~QQmlEngineDebugService()
+QQmlEngineDebugServiceImpl::~QQmlEngineDebugServiceImpl()
{
delete m_statesDelegate;
}
QDataStream &operator<<(QDataStream &ds,
- const QQmlEngineDebugService::QQmlObjectData &data)
+ const QQmlEngineDebugServiceImpl::QQmlObjectData &data)
{
ds << data.url << data.lineNumber << data.columnNumber << data.idString
<< data.objectName << data.objectType << data.objectId << data.contextId
@@ -85,7 +75,7 @@ QDataStream &operator<<(QDataStream &ds,
}
QDataStream &operator>>(QDataStream &ds,
- QQmlEngineDebugService::QQmlObjectData &data)
+ QQmlEngineDebugServiceImpl::QQmlObjectData &data)
{
ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
>> data.objectName >> data.objectType >> data.objectId >> data.contextId
@@ -94,7 +84,7 @@ QDataStream &operator>>(QDataStream &ds,
}
QDataStream &operator<<(QDataStream &ds,
- const QQmlEngineDebugService::QQmlObjectProperty &data)
+ const QQmlEngineDebugServiceImpl::QQmlObjectProperty &data)
{
ds << (int)data.type << data.name;
// check first whether the data can be saved
@@ -110,12 +100,12 @@ QDataStream &operator<<(QDataStream &ds,
}
QDataStream &operator>>(QDataStream &ds,
- QQmlEngineDebugService::QQmlObjectProperty &data)
+ QQmlEngineDebugServiceImpl::QQmlObjectProperty &data)
{
int type;
ds >> type >> data.name >> data.value >> data.valueTypeName
>> data.binding >> data.hasNotifySignal;
- data.type = (QQmlEngineDebugService::QQmlObjectProperty::Type)type;
+ data.type = (QQmlEngineDebugServiceImpl::QQmlObjectProperty::Type)type;
return ds;
}
@@ -142,8 +132,8 @@ static bool hasValidSignal(QObject *object, const QString &propertyName)
return true;
}
-QQmlEngineDebugService::QQmlObjectProperty
-QQmlEngineDebugService::propertyData(QObject *obj, int propIdx)
+QQmlEngineDebugServiceImpl::QQmlObjectProperty
+QQmlEngineDebugServiceImpl::propertyData(QObject *obj, int propIdx)
{
QQmlObjectProperty rv;
@@ -177,7 +167,7 @@ QQmlEngineDebugService::propertyData(QObject *obj, int propIdx)
return rv;
}
-QVariant QQmlEngineDebugService::valueContents(QVariant value) const
+QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
{
// We can't send JS objects across the wire, so transform them to variant
// maps for serialization.
@@ -192,6 +182,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;
@@ -237,7 +228,7 @@ QVariant QQmlEngineDebugService::valueContents(QVariant value) const
return QString(QStringLiteral("<unknown value>"));
}
-void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
+void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message,
QObject *object, bool recur, bool dumpProperties)
{
message << objectData(object);
@@ -277,13 +268,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 +279,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);
@@ -301,7 +288,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
}
fakeProperties << prop;
- signalHandler = signalHandler->m_nextSignal;
+ signalHandler = nextSignal(signalHandler);
}
}
@@ -314,7 +301,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
message << fakeProperties[ii];
}
-void QQmlEngineDebugService::prepareDeferredObjects(QObject *obj)
+void QQmlEngineDebugServiceImpl::prepareDeferredObjects(QObject *obj)
{
qmlExecuteDeferred(obj);
@@ -326,7 +313,7 @@ void QQmlEngineDebugService::prepareDeferredObjects(QObject *obj)
}
-void QQmlEngineDebugService::storeObjectIds(QObject *co)
+void QQmlEngineDebugServiceImpl::storeObjectIds(QObject *co)
{
QQmlDebugService::idForObject(co);
QObjectList children = co->children();
@@ -334,7 +321,7 @@ void QQmlEngineDebugService::storeObjectIds(QObject *co)
storeObjectIds(children.at(ii));
}
-void QQmlEngineDebugService::buildObjectList(QDataStream &message,
+void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message,
QQmlContext *ctxt,
const QList<QPointer<QObject> > &instances)
{
@@ -378,15 +365,15 @@ void QQmlEngineDebugService::buildObjectList(QDataStream &message,
}
}
-void QQmlEngineDebugService::buildStatesList(bool cleanList,
+void QQmlEngineDebugServiceImpl::buildStatesList(bool cleanList,
const QList<QPointer<QObject> > &instances)
{
if (m_statesDelegate)
m_statesDelegate->buildStatesList(cleanList, instances);
}
-QQmlEngineDebugService::QQmlObjectData
-QQmlEngineDebugService::objectData(QObject *object)
+QQmlEngineDebugServiceImpl::QQmlObjectData
+QQmlEngineDebugServiceImpl::objectData(QObject *object)
{
QQmlData *ddata = QQmlData::get(object);
QQmlObjectData rv;
@@ -425,12 +412,33 @@ QQmlEngineDebugService::objectData(QObject *object)
return rv;
}
-void QQmlEngineDebugService::messageReceived(const QByteArray &message)
+void QQmlEngineDebugServiceImpl::messageReceived(const QByteArray &message)
{
QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
}
-void QQmlEngineDebugService::processMessage(const QByteArray &message)
+/*!
+ Returns a list of objects matching the given filename, line and column.
+*/
+QList<QObject*> QQmlEngineDebugServiceImpl::objectForLocationInfo(const QString &filename,
+ int lineNumber, int columnNumber)
+{
+ QList<QObject *> objects;
+ const QHash<int, QObject *> &hash = objectsForIds();
+ for (QHash<int, QObject *>::ConstIterator i = hash.constBegin(); i != hash.constEnd(); ++i) {
+ QQmlData *ddata = QQmlData::get(i.value());
+ if (ddata && ddata->outerContext) {
+ if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
+ ddata->lineNumber == lineNumber &&
+ ddata->columnNumber >= columnNumber) {
+ objects << i.value();
+ }
+ }
+ }
+ return objects;
+}
+
+void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
{
QQmlDebugStream ds(message);
@@ -503,8 +511,7 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
ds >> file >> lineNumber >> columnNumber >> recurse >> dumpProperties;
- QList<QObject*> objects = QQmlDebugService::objectForLocationInfo(
- file, lineNumber, columnNumber);
+ QList<QObject*> objects = objectForLocationInfo(file, lineNumber, columnNumber);
rs << QByteArray("FETCH_OBJECTS_FOR_LOCATION_R") << queryId
<< objects.count();
@@ -610,10 +617,10 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
}
- sendMessage(reply);
+ emit messageToClient(name(), reply);
}
-bool QQmlEngineDebugService::setBinding(int objectId,
+bool QQmlEngineDebugServiceImpl::setBinding(int objectId,
const QString &propertyName,
const QVariant &expression,
bool isLiteralValue,
@@ -644,11 +651,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;
@@ -667,7 +672,7 @@ bool QQmlEngineDebugService::setBinding(int objectId,
return ok;
}
-bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyName)
+bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &propertyName)
{
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
@@ -679,12 +684,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
@@ -725,7 +725,7 @@ bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyN
return false;
}
-bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, const QString &body)
+bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &method, const QString &body)
{
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
@@ -762,22 +762,22 @@ 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;
}
-void QQmlEngineDebugService::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
+void QQmlEngineDebugServiceImpl::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
{
QByteArray reply;
QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
- sendMessage(reply);
+ emit messageToClient(name(), reply);
}
-void QQmlEngineDebugService::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlEngineDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(!m_engines.contains(engine));
@@ -786,7 +786,7 @@ void QQmlEngineDebugService::engineAboutToBeAdded(QQmlEngine *engine)
emit attachedToEngine(engine);
}
-void QQmlEngineDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlEngineDebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
@@ -795,7 +795,7 @@ void QQmlEngineDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
emit detachedFromEngine(engine);
}
-void QQmlEngineDebugService::objectCreated(QQmlEngine *engine, QObject *object)
+void QQmlEngineDebugServiceImpl::objectCreated(QQmlEngine *engine, QObject *object)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
@@ -809,10 +809,10 @@ void QQmlEngineDebugService::objectCreated(QQmlEngine *engine, QObject *object)
//unique queryId -1
rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId;
- sendMessage(reply);
+ emit messageToClient(name(), reply);
}
-void QQmlEngineDebugService::setStatesDelegate(QQmlDebugStatesDelegate *delegate)
+void QQmlEngineDebugServiceImpl::setStatesDelegate(QQmlDebugStatesDelegate *delegate)
{
m_statesDelegate = delegate;
}
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
index 0a824b132f..19a4827f89 100644
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLENGINEDEBUGSERVICE_P_H
-#define QQMLENGINEDEBUGSERVICE_P_H
+#ifndef QQMLENGINEDEBUGSERVICE_H
+#define QQMLENGINEDEBUGSERVICE_H
//
// W A R N I N G
@@ -46,6 +46,7 @@
//
#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <QtCore/qurl.h>
#include <QtCore/qvariant.h>
@@ -59,12 +60,12 @@ class QQmlWatcher;
class QDataStream;
class QQmlDebugStatesDelegate;
-class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : public QQmlDebugService
+class QQmlEngineDebugServiceImpl : public QQmlEngineDebugService
{
Q_OBJECT
public:
- QQmlEngineDebugService(QObject * = 0);
- ~QQmlEngineDebugService();
+ QQmlEngineDebugServiceImpl(QObject * = 0);
+ ~QQmlEngineDebugServiceImpl();
struct QQmlObjectData {
QUrl url;
@@ -94,8 +95,6 @@ public:
void setStatesDelegate(QQmlDebugStatesDelegate *);
- static QQmlEngineDebugService *instance();
-
protected:
virtual void messageReceived(const QByteArray &);
@@ -104,6 +103,8 @@ private Q_SLOTS:
void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
private:
+ friend class QQmlDebuggerServiceFactory;
+
void prepareDeferredObjects(QObject *);
void buildObjectList(QDataStream &, QQmlContext *,
const QList<QPointer<QObject> > &instances);
@@ -116,17 +117,19 @@ private:
bool resetBinding(int objectId, const QString &propertyName);
bool setMethodBody(int objectId, const QString &method, const QString &body);
void storeObjectIds(QObject *co);
+ QList<QObject *> objectForLocationInfo(const QString &filename, int lineNumber,
+ int columnNumber);
QList<QQmlEngine *> m_engines;
QQmlWatcher *m_watch;
QQmlDebugStatesDelegate *m_statesDelegate;
};
-Q_QML_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QQmlEngineDebugService::QQmlObjectData &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QQmlEngineDebugService::QQmlObjectData &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QQmlEngineDebugService::QQmlObjectProperty &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QQmlEngineDebugService::QQmlObjectProperty &);
+QDataStream &operator<<(QDataStream &, const QQmlEngineDebugServiceImpl::QQmlObjectData &);
+QDataStream &operator>>(QDataStream &, QQmlEngineDebugServiceImpl::QQmlObjectData &);
+QDataStream &operator<<(QDataStream &, const QQmlEngineDebugServiceImpl::QQmlObjectProperty &);
+QDataStream &operator>>(QDataStream &, QQmlEngineDebugServiceImpl::QQmlObjectProperty &);
QT_END_NAMESPACE
-#endif // QQMLENGINEDEBUGSERVICE_P_H
+#endif // QQMLENGINEDEBUGSERVICE_H
diff --git a/src/qml/qml/qqmlwatcher.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
index 9726b6f3b9..9f9a6eb33b 100644
--- a/src/qml/qml/qqmlwatcher.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
@@ -31,15 +31,15 @@
**
****************************************************************************/
-#include "qqmlwatcher_p.h"
+#include "qqmlwatcher.h"
#include "qqmlexpression.h"
#include "qqmlcontext.h"
#include "qqml.h"
#include <private/qqmldebugservice_p.h>
-#include "qqmlproperty_p.h"
-#include "qqmlvaluetype_p.h"
+#include <private/qqmlproperty_p.h>
+#include <private/qqmlvaluetype_p.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qdebug.h>
diff --git a/src/qml/qml/qqmlwatcher_p.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.h
index a7bb3c3418..329aee77d2 100644
--- a/src/qml/qml/qqmlwatcher_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLWATCHER_P_H
-#define QQMLWATCHER_P_H
+#ifndef QQMLWATCHER_H
+#define QQMLWATCHER_H
//
// W A R N I N G
@@ -83,4 +83,4 @@ private:
QT_END_NAMESPACE
-#endif // QQMLWATCHER_P_H
+#endif // QQMLWATCHER_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
new file mode 100644
index 0000000000..2ef7713ac7
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** 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 "qv4datacollector.h"
+
+#include <private/qv4script_p.h>
+#include <private/qv4string_p.h>
+#include <private/qv4objectiterator_p.h>
+#include <private/qv4identifier_p.h>
+#include <private/qv4runtime_p.h>
+
+#include <QtCore/qjsonarray.h>
+
+QT_BEGIN_NAMESPACE
+
+QV4::Heap::CallContext *QV4DataCollector::findContext(QV4::Heap::ExecutionContext *ctxt, int frame)
+{
+ if (!ctxt)
+ return 0;
+
+ QV4::Scope scope(ctxt->engine);
+ QV4::ScopedContext ctx(scope, ctxt);
+ while (ctx) {
+ QV4::CallContext *cCtxt = ctx->asCallContext();
+ if (cCtxt && cCtxt->d()->function) {
+ if (frame < 1)
+ return cCtxt->d();
+ --frame;
+ }
+ ctx = ctx->d()->parent;
+ }
+
+ return 0;
+}
+
+QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctxt, int scope)
+{
+ if (!ctxt)
+ return 0;
+
+ QV4::Scope s(ctxt->engine);
+ QV4::ScopedContext ctx(s, ctxt);
+ for (; scope > 0 && ctx; --scope)
+ ctx = ctx->d()->outer;
+
+ return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
+}
+
+QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeTypes(
+ QV4::ExecutionEngine *engine, int frame)
+{
+ QVector<QV4::Heap::ExecutionContext::ContextType> types;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::CallContext> sctxt(scope, findContext(engine->currentContext(), frame));
+ if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext)
+ return types;
+
+ QV4::ScopedContext it(scope, sctxt->d());
+ for (; it; it = it->d()->outer)
+ types.append(it->d()->type);
+
+ return types;
+}
+
+
+QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine)
+ : m_engine(engine), m_collectedRefs(Q_NULLPTR)
+{
+ values.set(engine, engine->newArrayObject());
+}
+
+QV4DataCollector::~QV4DataCollector()
+{
+}
+
+void QV4DataCollector::collect(const QV4::ScopedValue &value)
+{
+ if (m_collectedRefs)
+ m_collectedRefs->append(addRef(value));
+}
+
+const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::ExecutionEngine *engine,
+ QJsonObject &dict)
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedValue typeString(scope, QV4::Runtime::typeofValue(engine, value));
+ dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow());
+
+ const QLatin1String valueKey("value");
+ switch (value->type()) {
+ case QV4::Value::Empty_Type:
+ Q_ASSERT(!"empty Value encountered");
+ return 0;
+ case QV4::Value::Undefined_Type:
+ dict.insert(valueKey, QJsonValue::Undefined);
+ return 0;
+ case QV4::Value::Null_Type:
+ // "null" is not the correct type, but we leave this in until QtC can deal with "object"
+ dict.insert(QStringLiteral("type"), QStringLiteral("null"));
+ dict.insert(valueKey, QJsonValue::Null);
+ return 0;
+ case QV4::Value::Boolean_Type:
+ dict.insert(valueKey, value->booleanValue());
+ return 0;
+ case QV4::Value::Managed_Type:
+ if (const QV4::String *s = value->as<QV4::String>()) {
+ dict.insert(valueKey, s->toQString());
+ } else if (const QV4::ArrayObject *a = value->as<QV4::ArrayObject>()) {
+ // size of an array is number of its numerical properties; We don't consider free form
+ // object properties here.
+ dict.insert(valueKey, qint64(a->getLength()));
+ return a;
+ } else if (const QV4::Object *o = value->as<QV4::Object>()) {
+ int numProperties = 0;
+ QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
+ QV4::PropertyAttributes attrs;
+ uint index;
+ QV4::ScopedProperty p(scope);
+ QV4::ScopedString name(scope);
+ while (true) {
+ it.next(name.getRef(), &index, p, &attrs);
+ if (attrs.isEmpty())
+ break;
+ else
+ ++numProperties;
+ }
+ dict.insert(valueKey, numProperties);
+ return o;
+ } else {
+ Q_UNREACHABLE();
+ }
+ return 0;
+ case QV4::Value::Integer_Type:
+ dict.insert(valueKey, value->integerValue());
+ return 0;
+ default: // double
+ dict.insert(valueKey, value->doubleValue());
+ return 0;
+ }
+}
+
+QJsonObject QV4DataCollector::lookupRef(Ref ref)
+{
+ QJsonObject dict;
+ if (lookupSpecialRef(ref, &dict))
+ return dict;
+
+ dict.insert(QStringLiteral("handle"), qint64(ref));
+ QV4::Scope scope(engine());
+ QV4::ScopedValue value(scope, getValue(ref));
+
+ if (const QV4::Object *o = collectProperty(value, engine(), dict))
+ dict.insert(QStringLiteral("properties"), collectProperties(o));
+
+ return dict;
+}
+
+QV4DataCollector::Ref QV4DataCollector::addFunctionRef(const QString &functionName)
+{
+ Ref ref = addRef(QV4::Primitive::emptyValue(), false);
+
+ QJsonObject dict;
+ dict.insert(QStringLiteral("handle"), qint64(ref));
+ dict.insert(QStringLiteral("type"), QStringLiteral("function"));
+ dict.insert(QStringLiteral("name"), functionName);
+ specialRefs.insert(ref, dict);
+
+ return ref;
+}
+
+QV4DataCollector::Ref QV4DataCollector::addScriptRef(const QString &scriptName)
+{
+ Ref ref = addRef(QV4::Primitive::emptyValue(), false);
+
+ QJsonObject dict;
+ dict.insert(QStringLiteral("handle"), qint64(ref));
+ dict.insert(QStringLiteral("type"), QStringLiteral("script"));
+ dict.insert(QStringLiteral("name"), scriptName);
+ specialRefs.insert(ref, dict);
+
+ return ref;
+}
+
+void QV4DataCollector::collectScope(QJsonObject *dict, QV4::Debugging::Debugger *debugger,
+ int frameNr, int scopeNr)
+{
+ QStringList names;
+
+ Refs refs;
+ if (debugger->state() == QV4::Debugging::Debugger::Paused) {
+ RefHolder holder(this, &refs);
+ ArgumentCollectJob argumentsJob(m_engine, this, &names, frameNr, scopeNr);
+ debugger->runInEngine(&argumentsJob);
+ LocalCollectJob localsJob(m_engine, this, &names, frameNr, scopeNr);
+ debugger->runInEngine(&localsJob);
+ }
+
+ QV4::Scope scope(engine());
+ QV4::ScopedObject scopeObject(scope, engine()->newObject());
+
+ Q_ASSERT(names.size() == refs.size());
+ for (int i = 0, ei = refs.size(); i != ei; ++i)
+ scopeObject->put(engine(), names.at(i),
+ QV4::Value::fromReturnedValue(getValue(refs.at(i))));
+
+ Ref scopeObjectRef = addRef(scopeObject);
+ dict->insert(QStringLiteral("ref"), qint64(scopeObjectRef));
+ if (m_collectedRefs)
+ m_collectedRefs->append(scopeObjectRef);
+}
+
+QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicate)
+{
+ class ExceptionStateSaver
+ {
+ quint32 *hasExceptionLoc;
+ quint32 hadException;
+
+ public:
+ ExceptionStateSaver(QV4::ExecutionEngine *engine)
+ : hasExceptionLoc(&engine->hasException)
+ , hadException(false)
+ { std::swap(*hasExceptionLoc, hadException); }
+
+ ~ExceptionStateSaver()
+ { std::swap(*hasExceptionLoc, hadException); }
+ };
+
+ // if we wouldn't do this, the putIndexed won't work.
+ ExceptionStateSaver resetExceptionState(engine());
+ QV4::Scope scope(engine());
+ QV4::ScopedObject array(scope, values.value());
+ if (deduplicate) {
+ for (Ref i = 0; i < array->getLength(); ++i) {
+ if (array->getIndexed(i) == value.rawValue() && !specialRefs.contains(i))
+ return i;
+ }
+ }
+ Ref ref = array->getLength();
+ array->putIndexed(ref, value);
+ Q_ASSERT(array->getLength() - 1 == ref);
+ return ref;
+}
+
+QV4::ReturnedValue QV4DataCollector::getValue(Ref ref)
+{
+ QV4::Scope scope(engine());
+ QV4::ScopedObject array(scope, values.value());
+ Q_ASSERT(ref < array->getLength());
+ return array->getIndexed(ref, Q_NULLPTR);
+}
+
+bool QV4DataCollector::lookupSpecialRef(Ref ref, QJsonObject *dict)
+{
+ SpecialRefs::const_iterator it = specialRefs.find(ref);
+ if (it == specialRefs.end())
+ return false;
+
+ *dict = it.value();
+ return true;
+}
+
+QJsonArray QV4DataCollector::collectProperties(const QV4::Object *object)
+{
+ QJsonArray res;
+
+ QV4::Scope scope(engine());
+ QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
+ QV4::ScopedValue name(scope);
+ QV4::ScopedValue value(scope);
+ while (true) {
+ QV4::Value v;
+ name = it.nextPropertyNameAsString(&v);
+ if (name->isNull())
+ break;
+ QString key = name->toQStringNoThrow();
+ value = v;
+ res.append(collectAsJson(key, value));
+ }
+
+ return res;
+}
+
+QJsonObject QV4DataCollector::collectAsJson(const QString &name, const QV4::ScopedValue &value)
+{
+ QJsonObject dict;
+ if (!name.isNull())
+ dict.insert(QStringLiteral("name"), name);
+ if (value->isManaged() && !value->isString()) {
+ Ref ref = addRef(value);
+ dict.insert(QStringLiteral("ref"), qint64(ref));
+ if (m_collectedRefs)
+ m_collectedRefs->append(ref);
+ }
+
+ collectProperty(value, engine(), dict);
+ return dict;
+}
+
+ExpressionEvalJob::ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr,
+ const QString &expression,
+ QV4DataCollector *collector)
+ : JavaScriptJob(engine, frameNr, expression)
+ , collector(collector)
+{
+}
+
+void ExpressionEvalJob::handleResult(QV4::ScopedValue &result)
+{
+ if (hasExeption())
+ exception = result->toQStringNoThrow();
+ collector->collect(result);
+}
+
+const QString &ExpressionEvalJob::exceptionMessage() const
+{
+ return exception;
+}
+
+GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
+ : engine(engine)
+ , seq(seq)
+{}
+
+void GatherSourcesJob::run()
+{
+ QStringList sources;
+
+ foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
+ QString fileName = unit->fileName();
+ if (!fileName.isEmpty())
+ sources.append(fileName);
+ }
+
+ QV4::Debugging::Debugger *debugger = engine->debugger;
+ emit debugger->sourcesCollected(debugger, sources, seq);
+}
+
+ArgumentCollectJob::ArgumentCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ QStringList *names, int frameNr, int scopeNr)
+ : engine(engine)
+ , collector(collector)
+ , names(names)
+ , frameNr(frameNr)
+ , scopeNr(scopeNr)
+{}
+
+void ArgumentCollectJob::run()
+{
+ if (frameNr < 0)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::CallContext> ctxt(
+ scope, QV4DataCollector::findScope(
+ QV4DataCollector::findContext(engine->currentContext(), frameNr), scopeNr));
+ if (!ctxt)
+ return;
+
+ QV4::ScopedValue v(scope);
+ int nFormals = ctxt->formalCount();
+ for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = ctxt->formals()[nFormals - i - 1])
+ qName = name->string;
+ names->append(qName);
+ v = ctxt->argument(i);
+ collector->collect(v);
+ }
+}
+
+LocalCollectJob::LocalCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ QStringList *names, int frameNr, int scopeNr)
+ : engine(engine)
+ , collector(collector)
+ , names(names)
+ , frameNr(frameNr)
+ , scopeNr(scopeNr)
+{}
+
+void LocalCollectJob::run()
+{
+ if (frameNr < 0)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::CallContext> ctxt(
+ scope, QV4DataCollector::findScope(
+ QV4DataCollector::findContext(engine->currentContext(), frameNr), scopeNr));
+ if (!ctxt)
+ return;
+
+ QV4::ScopedValue v(scope);
+ for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = ctxt->variables()[i])
+ qName = name->string;
+ names->append(qName);
+ v = ctxt->d()->locals[i];
+ collector->collect(v);
+ }
+}
+
+ThisCollectJob::ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ int frameNr, bool *foundThis)
+ : engine(engine)
+ , collector(collector)
+ , frameNr(frameNr)
+ , foundThis(foundThis)
+{}
+
+void ThisCollectJob::run()
+{
+ *foundThis = myRun();
+}
+
+bool ThisCollectJob::myRun()
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine->currentContext(),
+ frameNr));
+ while (ctxt) {
+ if (QV4::CallContext *cCtxt = ctxt->asCallContext())
+ if (cCtxt->d()->activation)
+ break;
+ ctxt = ctxt->d()->outer;
+ }
+
+ if (!ctxt)
+ return false;
+
+ QV4::ScopedValue o(scope, ctxt->asCallContext()->d()->activation);
+ collector->collect(o);
+ return true;
+}
+
+ExceptionCollectJob::ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector)
+ : engine(engine)
+ , collector(collector)
+{}
+
+void ExceptionCollectJob::run()
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedValue v(scope, *engine->exceptionValue);
+ collector->collect(v);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
new file mode 100644
index 0000000000..7d26d71bdf
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** 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 QV4DATACOLLECTOR_H
+#define QV4DATACOLLECTOR_H
+
+#include <private/qv4engine_p.h>
+#include <private/qv4debugging_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV4DataCollector
+{
+public:
+ typedef uint Ref;
+ typedef QVector<uint> Refs;
+
+ static QV4::Heap::CallContext *findContext(QV4::Heap::ExecutionContext *ctxt, int frame);
+ static QV4::Heap::CallContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope);
+ static QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(
+ QV4::ExecutionEngine *engine, int frame);
+
+ QV4DataCollector(QV4::ExecutionEngine *engine);
+ ~QV4DataCollector();
+
+ void collect(const QV4::ScopedValue &value);
+
+ QJsonObject lookupRef(Ref ref);
+
+ Ref addFunctionRef(const QString &functionName);
+ Ref addScriptRef(const QString &scriptName);
+
+ void collectScope(QJsonObject *dict, QV4::Debugging::Debugger *debugger, int frameNr,
+ int scopeNr);
+
+ QV4::ExecutionEngine *engine() const { return m_engine; }
+
+private:
+ friend class RefHolder;
+
+ Ref addRef(QV4::Value value, bool deduplicate = true);
+ QV4::ReturnedValue getValue(Ref ref);
+ bool lookupSpecialRef(Ref ref, QJsonObject *dict);
+
+ QJsonArray collectProperties(const QV4::Object *object);
+ QJsonObject collectAsJson(const QString &name, const QV4::ScopedValue &value);
+ void collectArgumentsInContext();
+
+ QV4::ExecutionEngine *m_engine;
+ Refs *m_collectedRefs;
+ QV4::PersistentValue values;
+ typedef QHash<Ref, QJsonObject> SpecialRefs;
+ SpecialRefs specialRefs;
+};
+
+class RefHolder {
+public:
+ RefHolder(QV4DataCollector *collector, QV4DataCollector::Refs *target) :
+ m_collector(collector), m_previousRefs(collector->m_collectedRefs)
+ {
+ m_collector->m_collectedRefs = target;
+ }
+
+ ~RefHolder()
+ {
+ std::swap(m_collector->m_collectedRefs, m_previousRefs);
+ }
+
+private:
+ QV4DataCollector *m_collector;
+ QV4DataCollector::Refs *m_previousRefs;
+};
+
+class ExpressionEvalJob: public QV4::Debugging::Debugger::JavaScriptJob
+{
+ QV4DataCollector *collector;
+ QString exception;
+
+public:
+ ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, const QString &expression,
+ QV4DataCollector *collector);
+ virtual void handleResult(QV4::ScopedValue &result);
+ const QString &exceptionMessage() const;
+};
+
+class GatherSourcesJob: public QV4::Debugging::Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ const int seq;
+
+public:
+ GatherSourcesJob(QV4::ExecutionEngine *engine, int seq);
+ void run();
+};
+
+class ArgumentCollectJob: public QV4::Debugging::Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+ QStringList *names;
+ int frameNr;
+ int scopeNr;
+
+public:
+ ArgumentCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ QStringList *names, int frameNr, int scopeNr);
+ void run();
+};
+
+class LocalCollectJob: public QV4::Debugging::Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+ QStringList *names;
+ int frameNr;
+ int scopeNr;
+
+public:
+ LocalCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, QStringList *names,
+ int frameNr, int scopeNr);
+ void run();
+};
+
+class ThisCollectJob: public QV4::Debugging::Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+ int frameNr;
+ bool *foundThis;
+
+public:
+ ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, int frameNr,
+ bool *foundThis);
+ void run();
+ bool myRun();
+};
+
+class ExceptionCollectJob: public QV4::Debugging::Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+
+public:
+ ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector);
+ void run();
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DATACOLLECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
new file mode 100644
index 0000000000..7f22b16e45
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** 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 "qv4debuggeragent.h"
+#include "qv4debugservice.h"
+#include "qv4datacollector.h"
+
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonarray.h>
+
+QT_BEGIN_NAMESPACE
+
+QV4DebuggerAgent::QV4DebuggerAgent(QV4DebugServiceImpl *debugService)
+ : m_breakOnThrow(false), m_debugService(debugService)
+{}
+
+QV4::Debugging::Debugger *QV4DebuggerAgent::firstDebugger() const
+{
+ // Currently only 1 single engine is supported, so:
+ if (m_debuggers.isEmpty())
+ return 0;
+ else
+ return m_debuggers.first();
+}
+
+bool QV4DebuggerAgent::isRunning() const
+{
+ // Currently only 1 single engine is supported, so:
+ if (QV4::Debugging::Debugger *debugger = firstDebugger())
+ return debugger->state() == QV4::Debugging::Debugger::Running;
+ else
+ return false;
+}
+
+void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::Debugger *debugger,
+ QV4::Debugging::PauseReason reason)
+{
+ Q_UNUSED(reason);
+
+ m_debugService->clearHandles(debugger->engine());
+
+ QJsonObject event, body, script;
+ event.insert(QStringLiteral("type"), QStringLiteral("event"));
+
+ switch (reason) {
+ case QV4::Debugging::Step:
+ case QV4::Debugging::PauseRequest:
+ case QV4::Debugging::BreakPoint: {
+ event.insert(QStringLiteral("event"), QStringLiteral("break"));
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(1);
+ if (frames.isEmpty())
+ break;
+
+ const QV4::StackFrame &topFrame = frames.first();
+ body.insert(QStringLiteral("invocationText"), topFrame.function);
+ body.insert(QStringLiteral("sourceLine"), topFrame.line - 1);
+ if (topFrame.column > 0)
+ body.insert(QStringLiteral("sourceColumn"), topFrame.column);
+ QJsonArray breakPoints;
+ foreach (int breakPointId, breakPointIds(topFrame.source, topFrame.line))
+ breakPoints.push_back(breakPointId);
+ body.insert(QStringLiteral("breakpoints"), breakPoints);
+ script.insert(QStringLiteral("name"), topFrame.source);
+ } break;
+ case QV4::Debugging::Throwing:
+ // TODO: complete this!
+ event.insert(QStringLiteral("event"), QStringLiteral("exception"));
+ break;
+ }
+
+ if (!script.isEmpty())
+ body.insert(QStringLiteral("script"), script);
+ if (!body.isEmpty())
+ event.insert(QStringLiteral("body"), body);
+ m_debugService->send(event);
+}
+
+void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::Debugger *debugger,
+ const QStringList &sources, int requestSequenceNr)
+{
+ QJsonArray body;
+ foreach (const QString &source, sources) {
+ QJsonObject src;
+ src[QLatin1String("name")] = source;
+ src[QLatin1String("scriptType")] = 4;
+ body.append(src);
+ }
+
+ QJsonObject response;
+ response[QLatin1String("success")] = true;
+ response[QLatin1String("running")] = debugger->state() == QV4::Debugging::Debugger::Running;
+ response[QLatin1String("body")] = body;
+ response[QLatin1String("command")] = QStringLiteral("scripts");
+ response[QLatin1String("request_seq")] = requestSequenceNr;
+ response[QLatin1String("type")] = QStringLiteral("response");
+ m_debugService->send(response);
+}
+
+void QV4DebuggerAgent::addDebugger(QV4::Debugging::Debugger *debugger)
+{
+ Q_ASSERT(!m_debuggers.contains(debugger));
+ m_debuggers << debugger;
+
+ debugger->setBreakOnThrow(m_breakOnThrow);
+
+ foreach (const BreakPoint &breakPoint, m_breakPoints.values())
+ if (breakPoint.enabled)
+ debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
+
+ connect(debugger, SIGNAL(destroyed(QObject*)),
+ this, SLOT(handleDebuggerDeleted(QObject*)));
+ connect(debugger, SIGNAL(sourcesCollected(QV4::Debugging::Debugger*,QStringList,int)),
+ this, SLOT(sourcesCollected(QV4::Debugging::Debugger*,QStringList,int)),
+ Qt::QueuedConnection);
+ connect(debugger, SIGNAL(debuggerPaused(QV4::Debugging::Debugger*,QV4::Debugging::PauseReason)),
+ this, SLOT(debuggerPaused(QV4::Debugging::Debugger*,QV4::Debugging::PauseReason)),
+ Qt::QueuedConnection);
+}
+
+void QV4DebuggerAgent::removeDebugger(QV4::Debugging::Debugger *debugger)
+{
+ m_debuggers.removeAll(debugger);
+ disconnect(debugger, SIGNAL(destroyed(QObject*)),
+ this, SLOT(handleDebuggerDeleted(QObject*)));
+ disconnect(debugger, SIGNAL(sourcesCollected(QV4::Debugging::Debugger*,QStringList,int)),
+ this, SLOT(sourcesCollected(QV4::Debugging::Debugger*,QStringList,int)));
+ disconnect(debugger,
+ SIGNAL(debuggerPaused(QV4::Debugging::Debugger*,QV4::Debugging::PauseReason)),
+ this,
+ SLOT(debuggerPaused(QV4::Debugging::Debugger*,QV4::Debugging::PauseReason)));
+}
+
+void QV4DebuggerAgent::handleDebuggerDeleted(QObject *debugger)
+{
+ m_debuggers.removeAll(static_cast<QV4::Debugging::Debugger *>(debugger));
+}
+
+void QV4DebuggerAgent::pause(QV4::Debugging::Debugger *debugger) const
+{
+ debugger->pause();
+}
+
+void QV4DebuggerAgent::pauseAll() const
+{
+ foreach (QV4::Debugging::Debugger *debugger, m_debuggers)
+ pause(debugger);
+}
+
+void QV4DebuggerAgent::resumeAll() const
+{
+ foreach (QV4::Debugging::Debugger *debugger, m_debuggers)
+ if (debugger->state() == QV4::Debugging::Debugger::Paused)
+ debugger->resume(QV4::Debugging::Debugger::FullThrottle);
+}
+
+int QV4DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
+{
+ if (enabled)
+ foreach (QV4::Debugging::Debugger *debugger, m_debuggers)
+ debugger->addBreakPoint(fileName, lineNumber, condition);
+
+ int id = m_breakPoints.size();
+ m_breakPoints.insert(id, BreakPoint(fileName, lineNumber, enabled, condition));
+ return id;
+}
+
+void QV4DebuggerAgent::removeBreakPoint(int id)
+{
+ BreakPoint breakPoint = m_breakPoints.value(id);
+ if (!breakPoint.isValid())
+ return;
+
+ m_breakPoints.remove(id);
+
+ if (breakPoint.enabled)
+ foreach (QV4::Debugging::Debugger *debugger, m_debuggers)
+ debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
+}
+
+void QV4DebuggerAgent::removeAllBreakPoints()
+{
+ QList<int> ids = m_breakPoints.keys();
+ foreach (int id, ids)
+ removeBreakPoint(id);
+}
+
+void QV4DebuggerAgent::enableBreakPoint(int id, bool onoff)
+{
+ BreakPoint &breakPoint = m_breakPoints[id];
+ if (!breakPoint.isValid() || breakPoint.enabled == onoff)
+ return;
+ breakPoint.enabled = onoff;
+
+ foreach (QV4::Debugging::Debugger *debugger, m_debuggers) {
+ if (onoff)
+ debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
+ else
+ debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
+ }
+}
+
+QList<int> QV4DebuggerAgent::breakPointIds(const QString &fileName, int lineNumber) const
+{
+ QList<int> ids;
+
+ for (QHash<int, BreakPoint>::const_iterator i = m_breakPoints.begin(), ei = m_breakPoints.end(); i != ei; ++i)
+ if (i->lineNr == lineNumber && fileName.endsWith(i->fileName))
+ ids.push_back(i.key());
+
+ return ids;
+}
+
+void QV4DebuggerAgent::setBreakOnThrow(bool onoff)
+{
+ if (onoff != m_breakOnThrow) {
+ m_breakOnThrow = onoff;
+ foreach (QV4::Debugging::Debugger *debugger, m_debuggers)
+ debugger->setBreakOnThrow(onoff);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
new file mode 100644
index 0000000000..6126eea772
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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 QV4DEBUGGERAGENT_H
+#define QV4DEBUGGERAGENT_H
+
+#include <private/qv4debugging_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV4DebugServiceImpl;
+
+class QV4DebuggerAgent : public QObject
+{
+ Q_OBJECT
+public:
+ QV4DebuggerAgent(QV4DebugServiceImpl *m_debugService);
+
+ QV4::Debugging::Debugger *firstDebugger() const;
+ bool isRunning() const;
+
+ void addDebugger(QV4::Debugging::Debugger *debugger);
+ void removeDebugger(QV4::Debugging::Debugger *debugger);
+
+ void pause(QV4::Debugging::Debugger *debugger) const;
+ void pauseAll() const;
+ void resumeAll() const;
+ int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString());
+ void removeBreakPoint(int id);
+ void removeAllBreakPoints();
+ void enableBreakPoint(int id, bool onoff);
+ QList<int> breakPointIds(const QString &fileName, int lineNumber) const;
+
+ bool breakOnThrow() const { return m_breakOnThrow; }
+ void setBreakOnThrow(bool onoff);
+
+public slots:
+ void debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason);
+ void sourcesCollected(QV4::Debugging::Debugger *debugger, const QStringList &sources,
+ int requestSequenceNr);
+ void handleDebuggerDeleted(QObject *debugger);
+
+private:
+ QList<QV4::Debugging::Debugger *> m_debuggers;
+
+ struct BreakPoint {
+ QString fileName;
+ int lineNr;
+ bool enabled;
+ QString condition;
+
+ BreakPoint(): lineNr(-1), enabled(false) {}
+ BreakPoint(const QString &fileName, int lineNr, bool enabled, const QString &condition)
+ : fileName(fileName), lineNr(lineNr), enabled(enabled), condition(condition)
+ {}
+
+ bool isValid() const { return lineNr >= 0 && !fileName.isEmpty(); }
+ };
+
+ QHash<int, BreakPoint> m_breakPoints;
+ bool m_breakOnThrow;
+ QV4DebugServiceImpl *m_debugService;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DEBUGGERAGENT_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
new file mode 100644
index 0000000000..89820c9f56
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -0,0 +1,910 @@
+/****************************************************************************
+**
+** 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 "qv4debugservice.h"
+#include "qqmlengine.h"
+#include <private/qv4engine_p.h>
+#include <private/qv4function_p.h>
+#include <private/qqmldebugconnector_p.h>
+
+#include <private/qv8engine_p.h>
+
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonValue>
+
+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
+# define TRACE_PROTOCOL(x)
+#else
+#include <QtCore/QDebug>
+# define TRACE_PROTOCOL(x) x
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class V8CommandHandler;
+class UnknownV8CommandHandler;
+
+int QV4DebugServiceImpl::debuggerIndex = 0;
+int QV4DebugServiceImpl::sequence = 0;
+
+class V8CommandHandler
+{
+public:
+ V8CommandHandler(const QString &command)
+ : cmd(command)
+ {}
+
+ virtual ~V8CommandHandler()
+ {}
+
+ QString command() const { return cmd; }
+
+ void handle(const QJsonObject &request, QV4DebugServiceImpl *s)
+ {
+ TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
+
+ req = request;
+ seq = req.value(QStringLiteral("seq"));
+ debugService = s;
+
+ handleRequest();
+ if (!response.isEmpty()) {
+ response[QLatin1String("type")] = QStringLiteral("response");
+ debugService->send(response);
+ }
+
+ debugService = 0;
+ seq = QJsonValue();
+ req = QJsonObject();
+ response = QJsonObject();
+ }
+
+ virtual void handleRequest() = 0;
+
+protected:
+ void addCommand() { response.insert(QStringLiteral("command"), cmd); }
+ void addRequestSequence() { response.insert(QStringLiteral("request_seq"), seq); }
+ void addSuccess(bool success) { response.insert(QStringLiteral("success"), success); }
+ void addBody(const QJsonObject &body)
+ {
+ response.insert(QStringLiteral("body"), body);
+ }
+
+ void addRunning()
+ {
+ response.insert(QStringLiteral("running"), debugService->debuggerAgent.isRunning());
+ }
+
+ void addRefs()
+ {
+ response.insert(QStringLiteral("refs"), debugService->buildRefs());
+ }
+
+ void createErrorResponse(const QString &msg)
+ {
+ QJsonValue command = req.value(QStringLiteral("command"));
+ response.insert(QStringLiteral("command"), command);
+ addRequestSequence();
+ addSuccess(false);
+ addRunning();
+ response.insert(QStringLiteral("message"), msg);
+ }
+
+ int requestSequenceNr() const
+ { return seq.toInt(-1); }
+
+protected:
+ QString cmd;
+ QJsonObject req;
+ QJsonValue seq;
+ QV4DebugServiceImpl *debugService;
+ QJsonObject response;
+};
+
+class UnknownV8CommandHandler: public V8CommandHandler
+{
+public:
+ UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
+
+ virtual void handleRequest()
+ {
+ QString msg = QStringLiteral("unimplemented command \"");
+ msg += req.value(QStringLiteral("command")).toString();
+ msg += QStringLiteral("\"");
+ createErrorResponse(msg);
+ }
+};
+
+namespace {
+class V8VersionRequest: public V8CommandHandler
+{
+public:
+ V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
+
+ virtual void handleRequest()
+ {
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("V8Version"),
+ QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
+ addBody(body);
+ }
+};
+
+class V8SetBreakPointRequest: public V8CommandHandler
+{
+public:
+ V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
+ if (args.isEmpty())
+ return;
+
+ QString type = args.value(QStringLiteral("type")).toString();
+ if (type != QStringLiteral("scriptRegExp")) {
+ createErrorResponse(QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type));
+ return;
+ }
+
+ QString fileName = args.value(QStringLiteral("target")).toString();
+ if (fileName.isEmpty()) {
+ createErrorResponse(QStringLiteral("breakpoint has no file name"));
+ return;
+ }
+
+ int line = args.value(QStringLiteral("line")).toInt(-1);
+ if (line < 0) {
+ createErrorResponse(QStringLiteral("breakpoint has an invalid line number"));
+ return;
+ }
+
+ bool enabled = args.value(QStringLiteral("enabled")).toBool(true);
+ QString condition = args.value(QStringLiteral("condition")).toString();
+
+ // set the break point:
+ int id = debugService->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("type"), type);
+ body.insert(QStringLiteral("breakpoint"), id);
+ // It's undocumented, but V8 sends back an actual_locations array too. However, our
+ // Debugger currently doesn't tell us when it resolved a breakpoint, so we'll leave them
+ // pending until the breakpoint is hit for the first time.
+ addBody(body);
+ }
+};
+
+class V8ClearBreakPointRequest: public V8CommandHandler
+{
+public:
+ V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
+ if (args.isEmpty())
+ return;
+
+ int id = args.value(QStringLiteral("breakpoint")).toInt(-1);
+ if (id < 0) {
+ createErrorResponse(QStringLiteral("breakpoint has an invalid number"));
+ return;
+ }
+
+ // remove the break point:
+ debugService->debuggerAgent.removeBreakPoint(id);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("type"), QStringLiteral("scriptRegExp"));
+ body.insert(QStringLiteral("breakpoint"), id);
+ addBody(body);
+ }
+};
+
+class V8BacktraceRequest: public V8CommandHandler
+{
+public:
+ V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ int fromFrame = arguments.value(QStringLiteral("fromFrame")).toInt(0);
+ int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10);
+ // no idea what the bottom property is for, so we'll ignore it.
+
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+
+ QJsonArray frameArray;
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
+ for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
+ frameArray.push_back(debugService->buildFrame(frames[i], i, debugger));
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ if (frameArray.isEmpty()) {
+ body.insert(QStringLiteral("totalFrames"), 0);
+ } else {
+ body.insert(QStringLiteral("fromFrame"), fromFrame);
+ body.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
+ body.insert(QStringLiteral("frames"), frameArray);
+ }
+ addBody(body);
+ addRefs();
+ }
+};
+
+class V8FrameRequest: public V8CommandHandler
+{
+public:
+ V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ const int frameNr = arguments.value(QStringLiteral("number")).toInt(
+ debugService->selectedFrame());
+
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
+ if (frameNr < 0 || frameNr >= frames.size()) {
+ createErrorResponse(QStringLiteral("frame command has invalid frame number"));
+ return;
+ }
+
+ debugService->selectFrame(frameNr);
+ QJsonObject frame = debugService->buildFrame(frames[frameNr], frameNr, debugger);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(frame);
+ addRefs();
+ }
+};
+
+class V8ScopeRequest: public V8CommandHandler
+{
+public:
+ V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ const int frameNr = arguments.value(QStringLiteral("frameNumber")).toInt(
+ debugService->selectedFrame());
+ const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
+
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
+ if (frameNr < 0 || frameNr >= frames.size()) {
+ createErrorResponse(QStringLiteral("scope command has invalid frame number"));
+ return;
+ }
+ if (scopeNr < 0) {
+ createErrorResponse(QStringLiteral("scope command has invalid scope number"));
+ return;
+ }
+
+ QJsonObject scope = debugService->buildScope(frameNr, scopeNr, debugger);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(scope);
+ addRefs();
+ }
+};
+
+class V8LookupRequest: public V8CommandHandler
+{
+public:
+ V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QJsonArray handles = arguments.value(QStringLiteral("handles")).toArray();
+
+ QJsonObject body;
+ foreach (const QJsonValue &handle, handles)
+ body[QString::number(handle.toInt())] = debugService->lookup(handle.toInt());
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(body);
+ addRefs();
+ }
+};
+
+class V8ContinueRequest: public V8CommandHandler
+{
+public:
+ V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+
+ if (arguments.empty()) {
+ debugger->resume(QV4::Debugging::Debugger::FullThrottle);
+ } else {
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QString stepAction = arguments.value(QStringLiteral("stepaction")).toString();
+ const int stepcount = arguments.value(QStringLiteral("stepcount")).toInt(1);
+ if (stepcount != 1)
+ qWarning() << "Step count other than 1 is not supported.";
+
+ if (stepAction == QStringLiteral("in")) {
+ debugger->resume(QV4::Debugging::Debugger::StepIn);
+ } else if (stepAction == QStringLiteral("out")) {
+ debugger->resume(QV4::Debugging::Debugger::StepOut);
+ } else if (stepAction == QStringLiteral("next")) {
+ debugger->resume(QV4::Debugging::Debugger::StepOver);
+ } else {
+ createErrorResponse(QStringLiteral("continue command has invalid stepaction"));
+ return;
+ }
+ }
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ }
+};
+
+class V8DisconnectRequest: public V8CommandHandler
+{
+public:
+ V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
+
+ virtual void handleRequest()
+ {
+ debugService->debuggerAgent.removeAllBreakPoints();
+ debugService->debuggerAgent.resumeAll();
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ }
+};
+
+class V8SetExceptionBreakRequest: public V8CommandHandler
+{
+public:
+ V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
+
+ virtual void handleRequest()
+ {
+ bool wasEnabled = debugService->debuggerAgent.breakOnThrow();
+
+ //decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QString type = arguments.value(QStringLiteral("type")).toString();
+ bool enabled = arguments.value(QStringLiteral("number")).toBool(!wasEnabled);
+
+ if (type == QStringLiteral("all")) {
+ // that's fine
+ } else if (type == QStringLiteral("uncaught")) {
+ createErrorResponse(QStringLiteral("breaking only on uncaught exceptions is not supported yet"));
+ return;
+ } else {
+ createErrorResponse(QStringLiteral("invalid type for break on exception"));
+ return;
+ }
+
+ // do it:
+ debugService->debuggerAgent.setBreakOnThrow(enabled);
+
+ QJsonObject body;
+ body[QLatin1String("type")] = type;
+ body[QLatin1String("enabled")] = debugService->debuggerAgent.breakOnThrow();
+
+ // response:
+ addBody(body);
+ addRunning();
+ addSuccess(true);
+ addRequestSequence();
+ addCommand();
+ }
+};
+
+class V8ScriptsRequest: public V8CommandHandler
+{
+public:
+ V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
+
+ virtual void handleRequest()
+ {
+ //decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ int types = arguments.value(QStringLiteral("types")).toInt(-1);
+ if (types < 0 || types > 7) {
+ createErrorResponse(QStringLiteral("invalid types value in scripts command"));
+ return;
+ } else if (types != 4) {
+ createErrorResponse(QStringLiteral("unsupported types value in scripts command"));
+ return;
+ }
+
+ // do it:
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ GatherSourcesJob job(debugger->engine(), requestSequenceNr());
+ debugger->runInEngine(&job);
+
+ // response will be send by
+ }
+};
+
+// Request:
+// {
+// "seq": 4,
+// "type": "request",
+// "command": "evaluate",
+// "arguments": {
+// "expression": "a",
+// "frame": 0
+// }
+// }
+//
+// Response:
+// {
+// "body": {
+// "handle": 3,
+// "type": "number",
+// "value": 1
+// },
+// "command": "evaluate",
+// "refs": [],
+// "request_seq": 4,
+// "running": false,
+// "seq": 5,
+// "success": true,
+// "type": "response"
+// }
+//
+// The "value" key in "body" is the result of evaluating the expression in the request.
+class V8EvaluateRequest: public V8CommandHandler
+{
+public:
+ V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
+
+ virtual void handleRequest()
+ {
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ if (debugger->state() == QV4::Debugging::Debugger::Paused) {
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QString expression = arguments.value(QStringLiteral("expression")).toString();
+ const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
+
+ QV4DataCollector *collector = debugService->collector();
+ RefHolder holder(collector, debugService->refs());
+ ExpressionEvalJob job(debugger->engine(), frame, expression, collector);
+ debugger->runInEngine(&job);
+ if (job.hasExeption()) {
+ createErrorResponse(job.exceptionMessage());
+ } else {
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(collector->lookupRef(debugService->refs()->last()));
+ addRefs();
+ }
+ } else {
+ createErrorResponse(QStringLiteral("Debugger has to be paused for evaluate to work."));
+ }
+ }
+};
+} // anonymous namespace
+
+void QV4DebugServiceImpl::addHandler(V8CommandHandler* handler)
+{
+ handlers[handler->command()] = handler;
+}
+
+V8CommandHandler *QV4DebugServiceImpl::v8CommandHandler(const QString &command) const
+{
+ V8CommandHandler *handler = handlers.value(command, 0);
+ if (handler)
+ return handler;
+ else
+ return unknownV8CommandHandler.data();
+}
+
+QV4DebugServiceImpl::QV4DebugServiceImpl(QObject *parent) :
+ QQmlConfigurableDebugService<QV4DebugService>(1, parent),
+ debuggerAgent(this), version(1), theSelectedFrame(0),
+ unknownV8CommandHandler(new UnknownV8CommandHandler)
+{
+ addHandler(new V8VersionRequest);
+ addHandler(new V8SetBreakPointRequest);
+ addHandler(new V8ClearBreakPointRequest);
+ addHandler(new V8BacktraceRequest);
+ addHandler(new V8FrameRequest);
+ addHandler(new V8ScopeRequest);
+ addHandler(new V8LookupRequest);
+ addHandler(new V8ContinueRequest);
+ addHandler(new V8DisconnectRequest);
+ addHandler(new V8SetExceptionBreakRequest);
+ addHandler(new V8ScriptsRequest);
+ addHandler(new V8EvaluateRequest);
+}
+
+QV4DebugServiceImpl::~QV4DebugServiceImpl()
+{
+ qDeleteAll(handlers);
+}
+
+void QV4DebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
+{
+ QMutexLocker lock(&m_configMutex);
+ if (engine) {
+ QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) {
+ if (ee) {
+ ee->enableDebugger();
+ QV4::Debugging::Debugger *debugger = ee->debugger;
+ debuggerMap.insert(debuggerIndex++, debugger);
+ debuggerAgent.addDebugger(debugger);
+ debuggerAgent.moveToThread(server->thread());
+ }
+ }
+ }
+ QQmlConfigurableDebugService<QV4DebugService>::engineAboutToBeAdded(engine);
+}
+
+void QV4DebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
+{
+ QMutexLocker lock(&m_configMutex);
+ if (engine){
+ const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ if (ee) {
+ QV4::Debugging::Debugger *debugger = ee->debugger;
+ typedef QMap<int, QV4::Debugging::Debugger *>::const_iterator DebuggerMapIterator;
+ const DebuggerMapIterator end = debuggerMap.constEnd();
+ for (DebuggerMapIterator i = debuggerMap.constBegin(); i != end; ++i) {
+ if (i.value() == debugger) {
+ debuggerMap.remove(i.key());
+ break;
+ }
+ }
+ debuggerAgent.removeDebugger(debugger);
+ }
+ }
+ QQmlConfigurableDebugService<QV4DebugService>::engineAboutToBeRemoved(engine);
+}
+
+void QV4DebugServiceImpl::signalEmitted(const QString &signal)
+{
+ //This function is only called by QQmlBoundSignal
+ //only if there is a slot connected to the signal. Hence, there
+ //is no need for additional check.
+
+ //Parse just the name and remove the class info
+ //Normalize to Lower case.
+ QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
+
+ foreach (const QString &signal, breakOnSignals) {
+ if (signal == signalName) {
+ // TODO: pause debugger
+ break;
+ }
+ }
+}
+
+void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
+{
+ QMutexLocker lock(&m_configMutex);
+
+ QQmlDebugStream ms(message);
+ QByteArray header;
+ ms >> header;
+
+ TRACE_PROTOCOL(qDebug() << "received message with header" << header);
+
+ if (header == "V8DEBUG") {
+ QByteArray type;
+ QByteArray payload;
+ ms >> type >> payload;
+ TRACE_PROTOCOL(qDebug() << "... type:" << type);
+
+ if (type == V4_CONNECT) {
+ emit messageToClient(name(), packMessage(type));
+ stopWaiting();
+ } else if (type == V4_PAUSE) {
+ debuggerAgent.pauseAll();
+ sendSomethingToSomebody(type);
+ } else if (type == V4_BREAK_ON_SIGNAL) {
+ QByteArray signal;
+ bool enabled;
+ ms >> signal >> enabled;
+ //Normalize to lower case.
+ QString signalName(QString::fromUtf8(signal).toLower());
+ if (enabled)
+ breakOnSignals.append(signalName);
+ else
+ breakOnSignals.removeOne(signalName);
+ } else if (type == "v8request") {
+ handleV8Request(payload);
+ } else if (type == V4_DISCONNECT) {
+ TRACE_PROTOCOL(qDebug() << "... payload:" << payload.constData());
+ handleV8Request(payload);
+ } else {
+ sendSomethingToSomebody(type, 0);
+ }
+ }
+}
+
+void QV4DebugServiceImpl::sendSomethingToSomebody(const char *type, int magicNumber)
+{
+ QByteArray response;
+ QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ rs << QByteArray(type)
+ << QByteArray::number(version) << QByteArray::number(magicNumber);
+ emit messageToClient(name(), packMessage(type, response));
+}
+
+void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
+{
+ TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload.constData());
+
+ QJsonDocument request = QJsonDocument::fromJson(payload);
+ QJsonObject o = request.object();
+ QJsonValue type = o.value(QStringLiteral("type"));
+ if (type.toString() == QStringLiteral("request")) {
+ QJsonValue command = o.value(QStringLiteral("command"));
+ V8CommandHandler *h = v8CommandHandler(command.toString());
+ if (h)
+ h->handle(o, this);
+ }
+}
+
+QByteArray QV4DebugServiceImpl::packMessage(const QByteArray &command, const QByteArray &message)
+{
+ QByteArray reply;
+ QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ static const QByteArray cmd("V8DEBUG");
+ rs << cmd << command << message;
+ return reply;
+}
+
+void QV4DebugServiceImpl::send(QJsonObject v8Payload)
+{
+ v8Payload[QLatin1String("seq")] = sequence++;
+ QJsonDocument doc;
+ doc.setObject(v8Payload);
+#ifdef NO_PROTOCOL_TRACING
+ QByteArray responseData = doc.toJson(QJsonDocument::Compact);
+#else
+ QByteArray responseData = doc.toJson(QJsonDocument::Indented);
+#endif
+
+ TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData.constData() << endl);
+
+ emit messageToClient(name(), packMessage("v8message", responseData));
+}
+
+void QV4DebugServiceImpl::clearHandles(QV4::ExecutionEngine *engine)
+{
+ theCollector.reset(new QV4DataCollector(engine));
+}
+
+QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
+ QV4::Debugging::Debugger *debugger)
+{
+ QV4DataCollector::Ref ref;
+
+ QJsonObject frame;
+ frame[QLatin1String("index")] = frameNr;
+ frame[QLatin1String("debuggerFrame")] = false;
+ ref = theCollector->addFunctionRef(stackFrame.function);
+ collectedRefs.append(ref);
+ frame[QLatin1String("func")] = toRef(ref);
+ ref = theCollector->addScriptRef(stackFrame.source);
+ collectedRefs.append(ref);
+ frame[QLatin1String("script")] = toRef(ref);
+ frame[QLatin1String("line")] = stackFrame.line - 1;
+ if (stackFrame.column >= 0)
+ frame[QLatin1String("column")] = stackFrame.column;
+
+ QJsonArray scopes;
+ if (debugger->state() == QV4::Debugging::Debugger::Paused) {
+ RefHolder holder(theCollector.data(), &collectedRefs);
+ bool foundThis = false;
+ ThisCollectJob job(debugger->engine(), theCollector.data(), frameNr, &foundThis);
+ debugger->runInEngine(&job);
+ if (foundThis)
+ frame[QLatin1String("receiver")] = toRef(collectedRefs.last());
+
+ // Only type and index are used by Qt Creator, so we keep it easy:
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
+ QV4DataCollector::getScopeTypes(debugger->engine(), frameNr);
+ for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
+ int type = encodeScopeType(scopeTypes[i]);
+ if (type == -1)
+ continue;
+
+ QJsonObject scope;
+ scope[QLatin1String("index")] = i;
+ scope[QLatin1String("type")] = type;
+ scopes.push_back(scope);
+ }
+ }
+ frame[QLatin1String("scopes")] = scopes;
+
+ return frame;
+}
+
+int QV4DebugServiceImpl::encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
+{
+ switch (scopeType) {
+ case QV4::Heap::ExecutionContext::Type_GlobalContext:
+ return 0;
+ break;
+ case QV4::Heap::ExecutionContext::Type_CatchContext:
+ return 4;
+ break;
+ case QV4::Heap::ExecutionContext::Type_WithContext:
+ return 2;
+ break;
+ case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
+ case QV4::Heap::ExecutionContext::Type_CallContext:
+ return 1;
+ break;
+ case QV4::Heap::ExecutionContext::Type_QmlContext:
+ default:
+ return -1;
+ }
+}
+
+QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr,
+ QV4::Debugging::Debugger *debugger)
+{
+ QJsonObject scope;
+
+ QJsonObject object;
+ RefHolder holder(theCollector.data(), &collectedRefs);
+ theCollector->collectScope(&object, debugger, frameNr, scopeNr);
+
+ if (debugger->state() == QV4::Debugging::Debugger::Paused) {
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
+ QV4DataCollector::getScopeTypes(debugger->engine(), frameNr);
+ scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
+ } else {
+ scope[QLatin1String("type")] = -1;
+ }
+ scope[QLatin1String("index")] = scopeNr;
+ scope[QLatin1String("frameIndex")] = frameNr;
+ scope[QLatin1String("object")] = object;
+
+ return scope;
+}
+
+QJsonValue QV4DebugServiceImpl::lookup(QV4DataCollector::Ref refId)
+{
+ RefHolder holder(theCollector.data(), &collectedRefs);
+ return theCollector->lookupRef(refId);
+}
+
+QJsonArray QV4DebugServiceImpl::buildRefs()
+{
+ QJsonArray refs;
+ std::sort(collectedRefs.begin(), collectedRefs.end());
+ for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
+ QV4DataCollector::Ref ref = collectedRefs.at(i);
+ if (i > 0 && ref == collectedRefs.at(i - 1))
+ continue;
+ refs.append(lookup(ref));
+ }
+
+ collectedRefs.clear();
+ return refs;
+}
+
+QJsonValue QV4DebugServiceImpl::toRef(QV4DataCollector::Ref ref)
+{
+ QJsonObject dict;
+ dict.insert(QStringLiteral("ref"), qint64(ref));
+ return dict;
+}
+
+QV4DataCollector *QV4DebugServiceImpl::collector() const
+{
+ return theCollector.data();
+}
+
+QV4DataCollector::Refs *QV4DebugServiceImpl::refs()
+{
+ return &collectedRefs;
+}
+
+void QV4DebugServiceImpl::selectFrame(int frameNr)
+{
+ theSelectedFrame = frameNr;
+}
+
+int QV4DebugServiceImpl::selectedFrame() const
+{
+ return theSelectedFrame;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qv4debugservice_p.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
index f7b38b11b6..6c2950de8c 100644
--- a/src/qml/debugger/qv4debugservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QV4DEBUGSERVICE_P_H
-#define QV4DEBUGSERVICE_P_H
+#ifndef QV4DEBUGSERVICE_H
+#define QV4DEBUGSERVICE_H
//
// W A R N I N G
@@ -45,39 +45,82 @@
// We mean it.
//
-#include "qqmlconfigurabledebugservice_p.h"
+#include "qqmlconfigurabledebugservice.h"
+#include "qv4debuggeragent.h"
+#include "qv4datacollector.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qv4debugging_p.h>
+
+#include <QtCore/QJsonValue>
QT_BEGIN_NAMESPACE
namespace QV4 { struct ExecutionEngine; }
+
class QQmlEngine;
-class QV4DebugServicePrivate;
+class VariableCollector;
+class V8CommandHandler;
+class UnknownV8CommandHandler;
+class QV4DebugServiceImpl;
-class QV4DebugService : public QQmlConfigurableDebugService
+class QV4DebugServiceImpl : public QQmlConfigurableDebugService<QV4DebugService>
{
Q_OBJECT
public:
- explicit QV4DebugService(QObject *parent = 0);
- ~QV4DebugService();
+ explicit QV4DebugServiceImpl(QObject *parent = 0);
+ ~QV4DebugServiceImpl();
- static QV4DebugService *instance();
void engineAboutToBeAdded(QQmlEngine *engine);
void engineAboutToBeRemoved(QQmlEngine *engine);
void signalEmitted(const QString &signal);
+ void send(QJsonObject v8Payload);
+
+ QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::Debugger *debugger);
+ QJsonArray buildRefs();
+ QJsonValue lookup(QV4DataCollector::Ref refId);
+ QJsonValue toRef(QV4DataCollector::Ref ref);
+
+ QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
+ QV4::Debugging::Debugger *debugger);
+ int selectedFrame() const;
+ void selectFrame(int frameNr);
+
+ void clearHandles(QV4::ExecutionEngine *engine);
+
+ QV4DataCollector *collector() const;
+ QV4DebuggerAgent debuggerAgent;
+ QV4DataCollector::Refs *refs();
protected:
void messageReceived(const QByteArray &);
void sendSomethingToSomebody(const char *type, int magicNumber = 1);
private:
+ friend class QQmlDebuggerServiceFactory;
+
void handleV8Request(const QByteArray &payload);
+ static QByteArray packMessage(const QByteArray &command,
+ const QByteArray &message = QByteArray());
+ void processCommand(const QByteArray &command, const QByteArray &data);
+ V8CommandHandler *v8CommandHandler(const QString &command) const;
+ int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType);
-private:
- Q_DISABLE_COPY(QV4DebugService)
- Q_DECLARE_PRIVATE(QV4DebugService)
+ QStringList breakOnSignals;
+ QMap<int, QV4::Debugging::Debugger *> debuggerMap;
+ static int debuggerIndex;
+ static int sequence;
+ const int version;
+ QV4DataCollector::Refs collectedRefs;
+
+ QScopedPointer<QV4DataCollector> theCollector;
+ int theSelectedFrame;
+
+ void addHandler(V8CommandHandler* handler);
+ QHash<QString, V8CommandHandler*> handlers;
+ QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler;
};
QT_END_NAMESPACE
-#endif // QV4DEBUGSERVICE_P_H
+#endif // QV4DEBUGSERVICE_H
diff --git a/src/plugins/qmltooling/shared/abstracttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp
index 990bc704b9..3e059bed13 100644
--- a/src/plugins/qmltooling/shared/abstracttool.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp
@@ -35,6 +35,8 @@
#include "abstractviewinspector.h"
+QT_BEGIN_NAMESPACE
+
namespace QmlJSDebugger {
AbstractTool::AbstractTool(AbstractViewInspector *inspector) :
@@ -44,3 +46,5 @@ AbstractTool::AbstractTool(AbstractViewInspector *inspector) :
}
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/shared/abstracttool.h b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h
index 85f2b5b9ad..c796925866 100644
--- a/src/plugins/qmltooling/shared/abstracttool.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h
@@ -41,7 +41,6 @@ class QMouseEvent;
class QKeyEvent;
class QWheelEvent;
class QTouchEvent;
-QT_END_NAMESPACE
namespace QmlJSDebugger {
@@ -81,4 +80,6 @@ private:
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // ABSTRACTTOOL_H
diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
index e718cf022f..fa6dca7aca 100644
--- a/src/plugins/qmltooling/shared/abstractviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
@@ -32,14 +32,13 @@
****************************************************************************/
#include "abstractviewinspector.h"
-
#include "abstracttool.h"
#include <QtCore/QDebug>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtCore/private/qabstractanimation_p.h>
-#include <QtQml/private/qqmlinspectorservice_p.h>
+#include <QtQml/private/qqmldebugconnector_p.h>
#include <QtQml/private/qqmlcontext_p.h>
#include <QtGui/QMouseEvent>
@@ -61,6 +60,8 @@
// clearCache: void
// Response for "destroyObject" carries the <debugId_int> of the destroyed object.
+QT_BEGIN_NAMESPACE
+
const char REQUEST[] = "request";
const char RESPONSE[] = "response";
const char EVENT[] = "event";
@@ -78,10 +79,10 @@ const char CLEAR_CACHE[] = "clearCache";
namespace QmlJSDebugger {
-AbstractViewInspector::AbstractViewInspector(QObject *parent) :
+AbstractViewInspector::AbstractViewInspector(QQmlDebugService *service, QObject *parent) :
QObject(parent),
m_enabled(false),
- m_debugService(QQmlInspectorService::instance()),
+ m_debugService(service),
m_eventId(0),
m_reloadEventId(-1)
{
@@ -260,14 +261,13 @@ void AbstractViewInspector::onQmlObjectDestroyed(QObject *object)
return;
QPair<int, int> ids = m_hashObjectsTobeDestroyed.take(object);
- QQmlDebugService::removeInvalidObjectsFromHash();
QByteArray response;
QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(RESPONSE) << ids.first << true << ids.second;
- m_debugService->sendMessage(response);
+ emit m_debugService->messageToClient(m_debugService->name(), response);
}
void AbstractViewInspector::handleMessage(const QByteArray &message)
@@ -361,7 +361,7 @@ void AbstractViewInspector::handleMessage(const QByteArray &message)
QByteArray response;
QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(RESPONSE) << requestId << success;
- m_debugService->sendMessage(response);
+ emit m_debugService->messageToClient(m_debugService->name(), response);
}
void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
@@ -372,11 +372,12 @@ 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;
- m_debugService->sendMessage(message);
+ emit m_debugService->messageToClient(m_debugService->name(), message);
}
void AbstractViewInspector::sendQmlFileReloaded(bool success)
@@ -389,7 +390,7 @@ void AbstractViewInspector::sendQmlFileReloaded(bool success)
QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(RESPONSE) << m_reloadEventId << success;
- m_debugService->sendMessage(response);
+ emit m_debugService->messageToClient(m_debugService->name(), response);
}
QString AbstractViewInspector::idStringForObject(QObject *obj) const
@@ -414,3 +415,5 @@ void AbstractViewInspector::removeTool(AbstractTool *tool)
}
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h
index 02b4247bec..8f7ad4ac5b 100644
--- a/src/plugins/qmltooling/shared/abstractviewinspector.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h
@@ -38,18 +38,14 @@
#include <QtCore/QObject>
#include <QtCore/QStringList>
-#include "qmlinspectorconstants.h"
-
QT_BEGIN_NAMESPACE
class QQmlEngine;
-class QQmlInspectorService;
+class QQmlDebugService;
class QKeyEvent;
class QMouseEvent;
class QWheelEvent;
class QTouchEvent;
-QT_END_NAMESPACE
-
namespace QmlJSDebugger {
class AbstractTool;
@@ -62,7 +58,7 @@ class AbstractViewInspector : public QObject
Q_OBJECT
public:
- explicit AbstractViewInspector(QObject *parent = 0);
+ explicit AbstractViewInspector(QQmlDebugService *service, QObject *parent = 0);
void handleMessage(const QByteArray &message);
@@ -115,7 +111,7 @@ private:
bool m_enabled;
- QQmlInspectorService *m_debugService;
+ QQmlDebugService *m_debugService;
QList<AbstractTool *> m_tools;
int m_eventId;
int m_reloadEventId;
@@ -125,4 +121,6 @@ private:
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // ABSTRACTVIEWINSPECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp
index 5af7a225fd..4d4e3aa720 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp
@@ -38,8 +38,9 @@
#include <QtGui/QStaticText>
#include <QtQuick/QQuickWindow>
+QT_BEGIN_NAMESPACE
+
namespace QmlJSDebugger {
-namespace QtQuick2 {
Highlight::Highlight(QQuickItem *parent) : QQuickPaintedItem(parent)
{
@@ -193,5 +194,6 @@ void SelectionHighlight::disableNameDisplay()
update();
}
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.h b/src/plugins/qmltooling/qmldbg_inspector/highlight.h
index 29d2f0d911..05f6382353 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.h
@@ -39,9 +39,9 @@
#include <QtGui/QTransform>
#include <QtQuick/QQuickPaintedItem>
+QT_BEGIN_NAMESPACE
namespace QmlJSDebugger {
-namespace QtQuick2 {
class Highlight : public QQuickPaintedItem
{
@@ -104,7 +104,8 @@ public:
void paint(QPainter *painter);
};
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // HIGHLIGHT_H
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
index f86225fa0a..cc6b4ffb8c 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
@@ -48,8 +48,12 @@
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
+QT_BEGIN_NAMESPACE
+
namespace QmlJSDebugger {
-namespace QtQuick2 {
+
+static const double ZoomSnapDelta = 0.04;
+static const int PressAndHoldTimeout = 800;
InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
AbstractTool(inspector),
@@ -60,7 +64,7 @@ InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
m_tapEvent(false),
m_contentItem(view->contentItem()),
m_originalPosition(view->contentItem()->position()),
- m_smoothScaleFactor(Constants::ZoomSnapDelta),
+ m_smoothScaleFactor(ZoomSnapDelta),
m_minScale(0.125f),
m_maxScale(48.0f),
m_originalScale(view->contentItem()->scale()),
@@ -71,7 +75,7 @@ InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
{
//Press and Hold Timer
m_pressAndHoldTimer.setSingleShot(true);
- m_pressAndHoldTimer.setInterval(Constants::PressAndHoldTimeout);
+ m_pressAndHoldTimer.setInterval(PressAndHoldTimeout);
connect(&m_pressAndHoldTimer, SIGNAL(timeout()), SLOT(zoomTo100()));
//Timer to display selected item's name
m_nameDisplayTimer.setSingleShot(true);
@@ -418,5 +422,6 @@ void InspectTool::showSelectedItemName()
inspector()->showSelectedItemName(m_lastItem, m_mousePosition);
}
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h
index 0b1b49fd93..fdb763d4b3 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h
@@ -40,11 +40,12 @@
#include <QtCore/QPointer>
#include <QtCore/QTimer>
-QT_FORWARD_DECLARE_CLASS(QQuickView)
-QT_FORWARD_DECLARE_CLASS(QQuickItem)
+QT_BEGIN_NAMESPACE
+
+class QQuickView;
+class QQuickItem;
namespace QmlJSDebugger {
-namespace QtQuick2 {
class QQuickViewInspector;
class HoverHighlight;
@@ -119,7 +120,8 @@ private:
QQuickItem *m_lastClickedItem;
};
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // INSPECTTOOL_H
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
new file mode 100644
index 0000000000..1c3e5f387b
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
@@ -0,0 +1,27 @@
+TARGET = qmldbg_inspector
+QT += qml-private quick-private core-private gui-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlInspectorServiceFactory
+load(qt_plugin)
+
+INCLUDEPATH *= $$PWD $$PWD/../shared
+
+SOURCES += \
+ $$PWD/highlight.cpp \
+ $$PWD/qquickviewinspector.cpp \
+ $$PWD/abstracttool.cpp \
+ $$PWD/abstractviewinspector.cpp \
+ $$PWD/inspecttool.cpp \
+ $$PWD/qqmlinspectorservice.cpp
+
+HEADERS += \
+ $$PWD/highlight.h \
+ $$PWD/qquickviewinspector.h \
+ $$PWD/qqmlinspectorservicefactory.h \
+ $$PWD/abstracttool.h \
+ $$PWD/abstractviewinspector.h \
+ $$PWD/inspecttool.h
+
+OTHER_FILES += \
+ qqmlinspectorservice.json
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
new file mode 100644
index 0000000000..1707091df3
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** 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 "qqmlinspectorservicefactory.h"
+#include "qquickviewinspector.h"
+
+#include <private/qqmlglobal_p.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlInspectorServiceImpl : public QQmlInspectorService
+{
+ Q_OBJECT
+
+public:
+ QQmlInspectorServiceImpl(QObject *parent = 0);
+
+ void addView(QObject *);
+ void removeView(QObject *);
+
+protected:
+ virtual void stateChanged(State state);
+ virtual void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+ void processMessage(const QByteArray &message);
+ void updateState();
+
+private:
+ friend class QQmlInspectorServiceFactory;
+
+ QList<QObject*> m_views;
+ QmlJSDebugger::AbstractViewInspector *m_currentInspector;
+};
+
+QQmlInspectorServiceImpl::QQmlInspectorServiceImpl(QObject *parent):
+ QQmlInspectorService(1, parent), m_currentInspector(0)
+{
+}
+
+void QQmlInspectorServiceImpl::addView(QObject *view)
+{
+ m_views.append(view);
+ updateState();
+}
+
+void QQmlInspectorServiceImpl::removeView(QObject *view)
+{
+ m_views.removeAll(view);
+ updateState();
+}
+
+void QQmlInspectorServiceImpl::stateChanged(State /*state*/)
+{
+ QMetaObject::invokeMethod(this, "updateState", Qt::QueuedConnection);
+}
+
+void QQmlInspectorServiceImpl::updateState()
+{
+ delete m_currentInspector;
+ m_currentInspector = 0;
+
+ if (m_views.isEmpty() || state() != Enabled)
+ return;
+
+ QQuickView *qtQuickView = qobject_cast<QQuickView*>(m_views.first());
+ if (qtQuickView)
+ m_currentInspector = new QmlJSDebugger::QQuickViewInspector(this, qtQuickView, this);
+ else
+ qWarning() << "QQmlInspector: No inspector available for view '"
+ << m_views.first()->metaObject()->className() << "'.";
+}
+
+void QQmlInspectorServiceImpl::messageReceived(const QByteArray &message)
+{
+ QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
+}
+
+void QQmlInspectorServiceImpl::processMessage(const QByteArray &message)
+{
+ if (m_currentInspector)
+ m_currentInspector->handleMessage(message);
+}
+
+QQmlDebugService *QQmlInspectorServiceFactory::create(const QString &key)
+{
+ return key == QQmlInspectorServiceImpl::s_key ? new QQmlInspectorServiceImpl(this) : 0;
+}
+
+QT_END_NAMESPACE
+
+#include "qqmlinspectorservice.moc"
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json
new file mode 100644
index 0000000000..9ace8dad2f
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QmlInspector" ]
+}
diff --git a/src/qml/debugger/qqmlinspectorinterface_p.h b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h
index 9b29d383c7..52f84a362d 100644
--- a/src/qml/debugger/qqmlinspectorinterface_p.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLINSPECTORINTERFACE_H
-#define QQMLINSPECTORINTERFACE_H
+#ifndef QQMLINSPECTORSERVICE_H
+#define QQMLINSPECTORSERVICE_H
//
// W A R N I N G
@@ -45,30 +45,22 @@
// We mean it.
//
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmldebugservicefactory_p.h>
+
#include <QtQml/qtqmlglobal.h>
-#include <private/qqmlglobal_p.h>
+#include <QtCore/QList>
QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlInspectorInterface
+class QQmlInspectorServiceFactory : public QQmlDebugServiceFactory
{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmlinspectorservice.json")
public:
- QQmlInspectorInterface() {}
- virtual ~QQmlInspectorInterface() {}
-
- virtual bool canHandleView(QObject *view) = 0;
-
- virtual void activate(QObject *view) = 0;
- virtual void deactivate() = 0;
-
- virtual void clientMessage(const QByteArray &message) = 0;
+ QQmlDebugService *create(const QString &key);
};
-#define QQmlInspectorInterface_iid "org.qt-project.Qt.QQmlInspectorInterface"
-
-Q_DECLARE_INTERFACE(QQmlInspectorInterface, QQmlInspectorInterface_iid)
-
QT_END_NAMESPACE
-#endif // QQMLINSPECTORINTERFACE_H
+#endif // QQMLINSPECTORSERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp
index e61c421bfa..de9d5617b5 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp
@@ -37,7 +37,6 @@
#include "inspecttool.h"
#include <QtQml/private/qqmlengine_p.h>
-#include <QtQml/private/qqmldebugservice_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/QQuickView>
@@ -45,8 +44,8 @@
#include <cfloat>
+QT_BEGIN_NAMESPACE
namespace QmlJSDebugger {
-namespace QtQuick2 {
/*
* Collects all the items at the given position, from top to bottom.
@@ -110,8 +109,9 @@ static QQuickItem *itemAt(QQuickItem *item, const QPointF &pos,
}
-QQuickViewInspector::QQuickViewInspector(QQuickView *view, QObject *parent) :
- AbstractViewInspector(parent),
+QQuickViewInspector::QQuickViewInspector(QQmlDebugService *service, QQuickView *view,
+ QObject *parent) :
+ AbstractViewInspector(service, parent),
m_view(view),
m_overlay(new QQuickItem),
m_inspectTool(new InspectTool(this, view)),
@@ -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;
@@ -314,8 +315,6 @@ void QQuickViewInspector::reloadQmlFile(const QHash<QString, QByteArray> &change
// Reset the selection since we are reloading the main qml
setSelectedItems(QList<QQuickItem *>());
- QQmlDebugService::clearObjectsFromHash();
-
QHash<QUrl, QByteArray> debugCache;
foreach (const QString &str, changesHash.keys())
@@ -373,5 +372,6 @@ void QQuickViewInspector::applyAppOnTop()
setWindowFlags(flags);
}
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h
index be3ede4d07..e823e5a03d 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h
@@ -43,10 +43,8 @@
QT_BEGIN_NAMESPACE
class QQuickView;
class QQuickItem;
-QT_END_NAMESPACE
namespace QmlJSDebugger {
-namespace QtQuick2 {
class InspectTool;
class SelectionHighlight;
@@ -55,7 +53,7 @@ class QQuickViewInspector : public AbstractViewInspector
{
Q_OBJECT
public:
- explicit QQuickViewInspector(QQuickView *view, QObject *parent = 0);
+ explicit QQuickViewInspector(QQmlDebugService *service, QQuickView *view, QObject *parent = 0);
// AbstractViewInspector
void changeCurrentObjects(const QList<QObject*> &objects);
@@ -104,7 +102,8 @@ private:
bool m_appOnTop;
};
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // QQUICKVIEWINSPECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
new file mode 100644
index 0000000000..057bf9523e
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** 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 "qlocalclientconnectionfactory.h"
+#include "qpacketprotocol.h"
+#include "qqmldebugserver.h"
+
+#include <QtCore/qplugin.h>
+#include <QtNetwork/qlocalsocket.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QLocalClientConnection : public QQmlDebugServerConnection
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QLocalClientConnection)
+
+public:
+ QLocalClientConnection();
+ ~QLocalClientConnection();
+
+ void setServer(QQmlDebugServer *server);
+ bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress);
+ bool setFileName(const QString &filename, bool block);
+
+ bool isConnected() const;
+ void disconnect();
+
+ void waitForConnection();
+ void flush();
+
+private slots:
+ void connectionEstablished();
+
+private:
+ bool connectToServer();
+
+ bool m_block;
+ QString m_filename;
+ QLocalSocket *m_socket;
+ QQmlDebugServer *m_debugServer;
+};
+
+QLocalClientConnection::QLocalClientConnection() :
+ m_block(false),
+ m_socket(0),
+ m_debugServer(0)
+{
+}
+
+QLocalClientConnection::~QLocalClientConnection()
+{
+ if (isConnected())
+ disconnect();
+}
+
+void QLocalClientConnection::setServer(QQmlDebugServer *server)
+{
+ m_debugServer = server;
+}
+
+bool QLocalClientConnection::isConnected() const
+{
+ return m_socket && m_socket->state() == QLocalSocket::ConnectedState;
+}
+
+void QLocalClientConnection::disconnect()
+{
+ while (m_socket && m_socket->bytesToWrite() > 0)
+ m_socket->waitForBytesWritten();
+
+ m_socket->deleteLater();
+ m_socket = 0;
+}
+
+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)
+{
+ m_filename = filename;
+ m_block = block;
+ return connectToServer();
+}
+
+void QLocalClientConnection::waitForConnection()
+{
+ m_socket->waitForConnected(-1);
+}
+
+bool QLocalClientConnection::connectToServer()
+{
+ m_socket = new QLocalSocket;
+ m_socket->setParent(this);
+ QObject::connect(m_socket, SIGNAL(connected()), this, SLOT(connectionEstablished()));
+ m_socket->connectToServer(m_filename);
+ qDebug("QML Debugger: Connecting to socket %s...", m_filename.toLatin1().constData());
+ return true;
+}
+
+void QLocalClientConnection::flush()
+{
+ if (m_socket)
+ m_socket->flush();
+}
+
+void QLocalClientConnection::connectionEstablished()
+{
+ m_debugServer->setDevice(m_socket);
+}
+
+QQmlDebugServerConnection *QLocalClientConnectionFactory::create(const QString &key)
+{
+ return (key == QLatin1String("QLocalClientConnection") ? new QLocalClientConnection : 0);
+}
+
+QT_END_NAMESPACE
+
+#include "qlocalclientconnection.moc"
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json
new file mode 100644
index 0000000000..5f8fd49296
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QLocalClientConnection" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h
new file mode 100644
index 0000000000..110e0c2395
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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 QLOCALCLIENTCONNECTIONFACTORY_H
+#define QLOCALCLIENTCONNECTIONFACTORY_H
+
+#include "qqmldebugserverconnection.h"
+
+QT_BEGIN_NAMESPACE
+
+class QLocalClientConnectionFactory : public QQmlDebugServerConnectionFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServerConnectionFactory_iid FILE "qlocalclientconnection.json")
+ Q_INTERFACES(QQmlDebugServerConnectionFactory)
+public:
+ QQmlDebugServerConnection *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QLOCALCLIENTCONNECTIONFACTORY_H
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..491be04b15
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
@@ -0,0 +1,20 @@
+TARGET = qmldbg_local
+QT = qml-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QLocalClientConnectionFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qlocalclientconnection.cpp
+
+HEADERS += \
+ $$PWD/qlocalclientconnectionfactory.h \
+ $$PWD/../shared/qqmldebugserver.h \
+ $$PWD/../shared/qqmldebugserverconnection.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qlocalclientconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
new file mode 100644
index 0000000000..e1c4095d88
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
@@ -0,0 +1,28 @@
+TARGET = qmldbg_profiler
+QT = qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlProfilerServiceFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qqmlenginecontrolservice.cpp \
+ $$PWD/qqmlprofileradapter.cpp \
+ $$PWD/qqmlprofilerservice.cpp \
+ $$PWD/qqmlprofilerservicefactory.cpp \
+ $$PWD/qv4profileradapter.cpp
+
+HEADERS += \
+ $$PWD/../shared/qqmlconfigurabledebugservice.h \
+ $$PWD/qqmlenginecontrolservice.h \
+ $$PWD/qqmlprofileradapter.h \
+ $$PWD/qqmlprofilerservice.h \
+ $$PWD/qqmlprofilerservicefactory.h \
+ $$PWD/qv4profileradapter.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qqmlprofilerservice.json
+
diff --git a/src/qml/debugger/qqmlenginecontrolservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
index 07c6715524..4f131ac481 100644
--- a/src/qml/debugger/qqmlenginecontrolservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
@@ -31,24 +31,16 @@
**
****************************************************************************/
+#include "qqmlenginecontrolservice.h"
#include <QQmlEngine>
-#include "qqmldebug.h"
-#include "qqmlenginecontrolservice_p.h"
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QQmlEngineControlService, qmlEngineControlService)
+const QString QQmlEngineControlService::s_key = QStringLiteral("EngineControl");
-QQmlEngineControlService::QQmlEngineControlService() :
- QQmlDebugService(QStringLiteral("EngineControl"), 1)
+QQmlEngineControlService::QQmlEngineControlService(QObject *parent) :
+ QQmlDebugService(s_key, 1, parent)
{
- QMutexLocker lock(&dataMutex);
- registerService();
-}
-
-QQmlEngineControlService *QQmlEngineControlService::instance()
-{
- return qmlEngineControlService();
}
void QQmlEngineControlService::messageReceived(const QByteArray &message)
@@ -119,7 +111,7 @@ void QQmlEngineControlService::sendMessage(QQmlEngineControlService::MessageType
QByteArray message;
QQmlDebugStream d(&message, QIODevice::WriteOnly);
d << type << idForObject(engine);
- QQmlDebugService::sendMessage(message);
+ emit messageToClient(name(), message);
}
void QQmlEngineControlService::stateChanged(State)
diff --git a/src/qml/debugger/qqmlenginecontrolservice_p.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h
index 2171937efe..e2a93e562a 100644
--- a/src/qml/debugger/qqmlenginecontrolservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h
@@ -35,7 +35,7 @@
#define QQMLENGINECONTROLSERVICE_H
#include <QMutex>
-#include "qqmldebugservice_p.h"
+#include <private/qqmldebugservice_p.h>
//
// W A R N I N G
@@ -53,6 +53,8 @@ QT_BEGIN_NAMESPACE
class QQmlEngineControlService : public QQmlDebugService
{
public:
+ static const QString s_key;
+
enum MessageType {
EngineAboutToBeAdded,
EngineAdded,
@@ -65,9 +67,7 @@ public:
StopWaitingEngine
};
- QQmlEngineControlService();
-
- static QQmlEngineControlService *instance();
+ QQmlEngineControlService(QObject *parent = 0);
protected:
QMutex dataMutex;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
new file mode 100644
index 0000000000..349c181d13
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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 "qqmlprofileradapter.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
+ QQmlAbstractProfilerAdapter(service), next(0)
+{
+ engine->enableProfiler();
+ connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
+ connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
+ engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
+ connect(this, SIGNAL(profilingDisabledWhileWaiting()),
+ engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
+ engine->profiler, SLOT(setTimer(QElapsedTimer)));
+ connect(engine->profiler, SIGNAL(dataReady(QVector<QQmlProfilerData>)),
+ this, SLOT(receiveData(QVector<QQmlProfilerData>)));
+}
+
+// convert to QByteArrays that can be sent to the debug client
+// use of QDataStream can skew results
+// (see tst_qqmldebugtrace::trace() benchmark)
+static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteArray> &messages)
+{
+ QByteArray data;
+ Q_ASSERT_X(((d->messageType | d->detailType) & (1 << 31)) == 0, Q_FUNC_INFO,
+ "You can use at most 31 message types and 31 detail types.");
+ for (uint decodedMessageType = 0; (d->messageType >> decodedMessageType) != 0;
+ ++decodedMessageType) {
+ if ((d->messageType & (1 << decodedMessageType)) == 0)
+ continue;
+
+ for (uint decodedDetailType = 0; (d->detailType >> decodedDetailType) != 0;
+ ++decodedDetailType) {
+ if ((d->detailType & (1 << decodedDetailType)) == 0)
+ continue;
+
+ //### using QDataStream is relatively expensive
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ ds << d->time << decodedMessageType << decodedDetailType;
+
+ switch (decodedMessageType) {
+ case QQmlProfilerDefinitions::RangeStart:
+ if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
+ ds << QQmlProfilerDefinitions::QmlBinding;
+ break;
+ case QQmlProfilerDefinitions::RangeData:
+ ds << d->detailString;
+ break;
+ case QQmlProfilerDefinitions::RangeLocation:
+ ds << (d->detailUrl.isEmpty() ? d->detailString : d->detailUrl.toString()) << d->x
+ << d->y;
+ break;
+ case QQmlProfilerDefinitions::RangeEnd: break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+ break;
+ }
+ messages << data;
+ data.clear();
+ }
+ }
+}
+
+qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+ while (next != data.length()) {
+ if (data[next].time > until)
+ return data[next].time;
+ qQmlProfilerDataToByteArrays(&(data[next++]), messages);
+ }
+
+ next = 0;
+ data.clear();
+ return -1;
+}
+
+void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data)
+{
+ if (data.isEmpty())
+ data = new_data;
+ else
+ data.append(new_data);
+ service->dataReady(this);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index 6d693b6352..eceb58ce3a 100644
--- a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -31,9 +31,6 @@
**
****************************************************************************/
-#ifndef QQMLCONFIGURABLEDEBUGSERVICE_P_H
-#define QQMLCONFIGURABLEDEBUGSERVICE_P_H
-
//
// W A R N I N G
// -------------
@@ -45,26 +42,28 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
+#ifndef QQMLPROFILERADAPTER_H
+#define QQMLPROFILERADAPTER_H
-#include <QMutex>
+#include <private/qqmlabstractprofileradapter_p.h>
+#include <private/qqmlprofiler_p.h>
QT_BEGIN_NAMESPACE
-class QQmlEngine;
-
-class QQmlConfigurableDebugServicePrivate : public QQmlDebugServicePrivate
-{
- Q_DECLARE_PUBLIC(QQmlConfigurableDebugService)
+class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
+ Q_OBJECT
public:
- QQmlConfigurableDebugServicePrivate() : configMutex(QMutex::Recursive) {}
+ QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+
+public slots:
+ void receiveData(const QVector<QQmlProfilerData> &new_data);
- QMutex configMutex;
- QList<QQmlEngine *> waitingEngines;
- bool waitingForConfiguration;
+private:
+ QVector<QQmlProfilerData> data;
+ int next;
};
QT_END_NAMESPACE
-#endif // QQMLCONFIGURABLEDEBUGSERVICE_P_H
+#endif // QQMLPROFILERADAPTER_H
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index 85556836e6..65b99ef7ca 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -31,10 +31,10 @@
**
****************************************************************************/
-#include "qqmlprofilerservice_p.h"
-#include "qqmldebugserver_p.h"
-#include "qv4profileradapter_p.h"
-#include "qqmlprofiler_p.h"
+#include "qqmlprofilerservice.h"
+#include "qv4profileradapter.h"
+#include "qqmlprofileradapter.h"
+#include "qqmlprofilerservicefactory.h"
#include <private/qqmlengine_p.h>
#include <QtCore/qdatastream.h>
@@ -45,20 +45,14 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance)
-
-QQmlProfilerService::QQmlProfilerService()
- : QQmlConfigurableDebugService(QStringLiteral("CanvasFrameRate"), 1)
+QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) :
+ QQmlConfigurableDebugService<QQmlProfilerService>(1, parent),
+ m_waitingForStop(false)
{
m_timer.start();
-
- QMutexLocker lock(configMutex());
- // If there is no debug server it doesn't matter as we'll never get enabled anyway.
- if (QQmlDebugServer::instance() != 0)
- moveToThread(QQmlDebugServer::instance()->thread());
}
-QQmlProfilerService::~QQmlProfilerService()
+QQmlProfilerServiceImpl::~QQmlProfilerServiceImpl()
{
// No need to lock here. If any engine or global profiler is still trying to register at this
// point we have a nasty bug anyway.
@@ -66,9 +60,9 @@ QQmlProfilerService::~QQmlProfilerService()
qDeleteAll(m_globalProfilers);
}
-void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::dataReady(QQmlAbstractProfilerAdapter *profiler)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
bool dataComplete = true;
for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin()); i != m_startTimes.end();) {
if (i.value() == profiler) {
@@ -98,38 +92,35 @@ void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler)
}
}
-QQmlProfilerService *QQmlProfilerService::instance()
-{
- // just make sure that the service is properly registered
- return profilerInstance();
-}
-
-void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be added from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine));
QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
addEngineProfiler(qmlAdapter, engine);
addEngineProfiler(v4Adapter, engine);
- QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
+ QQmlConfigurableDebugService<QQmlProfilerService>::engineAboutToBeAdded(engine);
}
-void QQmlProfilerService::engineAdded(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAdded(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be added from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine))
profiler->stopWaiting();
}
-void QQmlProfilerService::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be removed from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
bool isRunning = false;
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
if (profiler->isRunning())
@@ -144,11 +135,12 @@ void QQmlProfilerService::engineAboutToBeRemoved(QQmlEngine *engine)
}
}
-void QQmlProfilerService::engineRemoved(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineRemoved(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be removed from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
removeProfilerFromStartTimes(profiler);
delete profiler;
@@ -156,16 +148,16 @@ void QQmlProfilerService::engineRemoved(QQmlEngine *engine)
m_engineProfilers.remove(engine);
}
-void QQmlProfilerService::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine)
+void QQmlProfilerServiceImpl::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine)
{
profiler->moveToThread(thread());
profiler->synchronize(m_timer);
m_engineProfilers.insert(engine, profiler);
}
-void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
profiler->synchronize(m_timer);
m_globalProfilers.append(profiler);
// Global profiler, not connected to a specific engine.
@@ -179,15 +171,15 @@ void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profile
profiler->startProfiling(features);
}
-void QQmlProfilerService::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
removeProfilerFromStartTimes(profiler);
m_globalProfilers.removeOne(profiler);
delete profiler;
}
-void QQmlProfilerService::removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler)
{
for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin());
i != m_startTimes.end();) {
@@ -206,9 +198,9 @@ void QQmlProfilerService::removeProfilerFromStartTimes(const QQmlAbstractProfile
*
* If any engine profiler is started like that also start all global profilers.
*/
-void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
+void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 features)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QByteArray message;
QQmlDebugStream d(&message, QIODevice::WriteOnly);
@@ -243,9 +235,11 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
if (!profiler->isRunning())
profiler->startProfiling(features);
}
+
+ emit startFlushTimer();
}
- QQmlDebugService::sendMessage(message);
+ emit messageToClient(name(), message);
}
/*!
@@ -255,9 +249,9 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
* If afterwards no more engine profilers are running, also stop all global profilers. Otherwise
* only make them report their data.
*/
-void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::stopProfiling(QQmlEngine *engine)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QList<QQmlAbstractProfilerAdapter *> stopping;
QList<QQmlAbstractProfilerAdapter *> reporting;
@@ -274,6 +268,9 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
}
}
+ if (stopping.isEmpty())
+ return;
+
foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
if (!profiler->isRunning())
continue;
@@ -285,6 +282,9 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
}
}
+ emit stopFlushTimer();
+ m_waitingForStop = true;
+
foreach (QQmlAbstractProfilerAdapter *profiler, reporting)
profiler->reportData();
@@ -295,21 +295,24 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
/*
Send the queued up messages.
*/
-void QQmlProfilerService::sendMessages()
+void QQmlProfilerServiceImpl::sendMessages()
{
QList<QByteArray> messages;
QByteArray data;
- QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
- traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
- QSet<QQmlEngine *> seen;
- foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) {
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
- i != m_engineProfilers.end(); ++i) {
- if (i.value() == profiler && !seen.contains(i.key())) {
- seen << i.key();
- traceEnd << idForObject(i.key());
+ if (m_waitingForStop) {
+ QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
+ traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
+
+ QSet<QQmlEngine *> seen;
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) {
+ for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
+ i != m_engineProfilers.end(); ++i) {
+ if (i.value() == profiler && !seen.contains(i.key())) {
+ seen << i.key();
+ traceEnd << idForObject(i.key());
+ }
}
}
}
@@ -326,20 +329,31 @@ void QQmlProfilerService::sendMessages()
}
}
- //indicate completion
- messages << data;
- data.clear();
+ if (m_waitingForStop) {
+ //indicate completion
+ messages << data;
+ data.clear();
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << (qint64)-1 << (int)Complete;
- messages << data;
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ ds << (qint64)-1 << (int)Complete;
+ messages << data;
+ m_waitingForStop = false;
+ }
+
+ emit messagesToClient(name(), messages);
- QQmlDebugService::sendMessages(messages);
+ // Restart flushing if any profilers are still running
+ foreach (const QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
+ if (profiler->isRunning()) {
+ emit startFlushTimer();
+ break;
+ }
+ }
}
-void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
+void QQmlProfilerServiceImpl::stateAboutToBeChanged(QQmlDebugService::State newState)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
if (state() == newState)
return;
@@ -351,9 +365,9 @@ void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState
}
}
-void QQmlProfilerService::messageReceived(const QByteArray &message)
+void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QByteArray rwData = message;
QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
@@ -361,11 +375,25 @@ void QQmlProfilerService::messageReceived(const QByteArray &message)
int engineId = -1;
quint64 features = std::numeric_limits<quint64>::max();
bool enabled;
+ uint flushInterval = 0;
stream >> enabled;
if (!stream.atEnd())
stream >> engineId;
if (!stream.atEnd())
stream >> features;
+ if (!stream.atEnd()) {
+ stream >> flushInterval;
+ m_flushTimer.setInterval(flushInterval);
+ if (flushInterval > 0) {
+ connect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush()));
+ connect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start()));
+ connect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
+ } else {
+ disconnect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush()));
+ disconnect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start()));
+ disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
+ }
+ }
// If engineId == -1 objectForId() and then the cast will return 0.
if (enabled)
@@ -376,4 +404,23 @@ void QQmlProfilerService::messageReceived(const QByteArray &message)
stopWaiting();
}
+void QQmlProfilerServiceImpl::flush()
+{
+ QMutexLocker lock(&m_configMutex);
+
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
+ if (profiler->isRunning()) {
+ m_startTimes.insert(-1, profiler);
+ profiler->reportData();
+ }
+ }
+
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
+ if (profiler->isRunning()) {
+ m_startTimes.insert(-1, profiler);
+ profiler->reportData();
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
index 978d8413a7..9b139ffabb 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
@@ -45,10 +45,10 @@
// We mean it.
//
-#include "qqmlconfigurabledebugservice_p.h"
-#include "qqmlprofilerdefinitions_p.h"
-#include "qqmlabstractprofileradapter_p.h"
-
+#include "qqmlconfigurabledebugservice.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmlprofilerdefinitions_p.h>
+#include <private/qqmlabstractprofileradapter_p.h>
#include <private/qqmlboundsignal_p.h>
#include <QtCore/qelapsedtimer.h>
@@ -57,6 +57,7 @@
#include <QtCore/qvector.h>
#include <QtCore/qstringbuilder.h>
#include <QtCore/qwaitcondition.h>
+#include <QtCore/qtimer.h>
#include <limits>
@@ -66,12 +67,13 @@ class QUrl;
class QQmlEngine;
-class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlConfigurableDebugService, public QQmlProfilerDefinitions
+class QQmlProfilerServiceImpl :
+ public QQmlConfigurableDebugService<QQmlProfilerService>,
+ public QQmlProfilerDefinitions
{
Q_OBJECT
public:
- static QQmlProfilerService *instance();
void engineAboutToBeAdded(QQmlEngine *engine);
void engineAboutToBeRemoved(QQmlEngine *engine);
void engineAdded(QQmlEngine *engine);
@@ -83,22 +85,32 @@ public:
void startProfiling(QQmlEngine *engine, quint64 features = std::numeric_limits<quint64>::max());
void stopProfiling(QQmlEngine *engine);
- QQmlProfilerService();
- ~QQmlProfilerService();
+ QQmlProfilerServiceImpl(QObject *parent = 0);
+ ~QQmlProfilerServiceImpl();
void dataReady(QQmlAbstractProfilerAdapter *profiler);
+signals:
+ void startFlushTimer();
+ void stopFlushTimer();
+
+private slots:
+ void flush();
+
protected:
virtual void stateAboutToBeChanged(State state);
virtual void messageReceived(const QByteArray &);
private:
+ friend class QQmlProfilerServiceFactory;
void sendMessages();
void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine);
void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler);
QElapsedTimer m_timer;
+ QTimer m_flushTimer;
+ bool m_waitingForStop;
QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json
new file mode 100644
index 0000000000..ec1ec364da
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "CanvasFrameRate", "EngineControl" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp
new file mode 100644
index 0000000000..83c2075246
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** 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 "qqmlprofilerservice.h"
+#include "qqmlenginecontrolservice.h"
+#include "qqmlprofilerservicefactory.h"
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebugService *QQmlProfilerServiceFactory::create(const QString &key)
+{
+ if (key == QQmlProfilerServiceImpl::s_key)
+ return new QQmlProfilerServiceImpl(this);
+
+ if (key == QQmlEngineControlService::s_key)
+ return new QQmlEngineControlService(this);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h
new file mode 100644
index 0000000000..b570136e5b
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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 QQMLPROFILERSERVICE_H
+#define QQMLPROFILERSERVICE_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/qqmldebugservicefactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlProfilerServiceFactory : public QQmlDebugServiceFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmlprofilerservice.json")
+public:
+ QQmlDebugService *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILERSERVICE_H
diff --git a/src/qml/debugger/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index 2b8183dc69..24e01f4c68 100644
--- a/src/qml/debugger/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -31,14 +31,13 @@
**
****************************************************************************/
-#include "qv4profileradapter_p.h"
-#include "qqmlprofilerservice_p.h"
-#include "qqmldebugservice_p.h"
+#include "qv4profileradapter.h"
+#include "qqmlprofilerservice.h"
QT_BEGIN_NAMESPACE
QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) :
- QQmlAbstractProfilerAdapter(service)
+ QQmlAbstractProfilerAdapter(service), dataPos(0), memoryPos(0)
{
engine->enableProfiler();
connect(this, SIGNAL(profilingEnabled(quint64)),
@@ -51,45 +50,63 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QList<QV4::Profiling::FunctionCallProperties>,
- QList<QV4::Profiling::MemoryAllocationProperties>)),
- this, SLOT(receiveData(QList<QV4::Profiling::FunctionCallProperties>,
- QList<QV4::Profiling::MemoryAllocationProperties>)));
+ connect(engine->profiler, SIGNAL(dataReady(QVector<QV4::Profiling::FunctionCallProperties>,
+ QVector<QV4::Profiling::MemoryAllocationProperties>)),
+ this, SLOT(receiveData(QVector<QV4::Profiling::FunctionCallProperties>,
+ QVector<QV4::Profiling::MemoryAllocationProperties>)));
}
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages)
{
QByteArray message;
- while (!memory_data.empty() && memory_data.front().timestamp <= until) {
+ while (memory_data.length() > memoryPos && memory_data[memoryPos].timestamp <= until) {
QQmlDebugStream d(&message, QIODevice::WriteOnly);
- QV4::Profiling::MemoryAllocationProperties &props = memory_data.front();
+ QV4::Profiling::MemoryAllocationProperties &props = memory_data[memoryPos];
d << props.timestamp << MemoryAllocation << props.type << props.size;
- memory_data.pop_front();
+ ++memoryPos;
messages.append(message);
}
- return memory_data.empty() ? -1 : memory_data.front().timestamp;
+ return memory_data.length() == memoryPos ? -1 : memory_data[memoryPos].timestamp;
+}
+
+qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
+ qint64 callNext)
+{
+ if (callNext == -1) {
+ data.clear();
+ dataPos = 0;
+ }
+
+ qint64 memoryNext = appendMemoryEvents(until, messages);
+
+ if (memoryNext == -1) {
+ memory_data.clear();
+ memoryPos = 0;
+ return callNext;
+ }
+
+ return callNext == -1 ? memoryNext : qMin(callNext, memoryNext);
}
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
QByteArray message;
while (true) {
- while (!stack.empty() && (data.empty() || stack.top() <= data.front().start)) {
- if (stack.top() > until) {
- qint64 memory_next = appendMemoryEvents(until, messages);
- return memory_next == -1 ? stack.top() : qMin(stack.top(), memory_next);
- }
+ while (!stack.isEmpty() && (dataPos == data.length() ||
+ stack.top() <= data[dataPos].start)) {
+ if (stack.top() > until)
+ return finalizeMessages(until, messages, stack.top());
+
appendMemoryEvents(stack.top(), messages);
QQmlDebugStream d(&message, QIODevice::WriteOnly);
d << stack.pop() << RangeEnd << Javascript;
messages.append(message);
}
- while (!data.empty() && (stack.empty() || data.front().start < stack.top())) {
- const QV4::Profiling::FunctionCallProperties &props = data.front();
- if (props.start > until) {
- qint64 memory_next = appendMemoryEvents(until, messages);
- return memory_next == -1 ? props.start : qMin(props.start, memory_next);
- }
+ while (dataPos != data.length() && (stack.empty() || data[dataPos].start < stack.top())) {
+ const QV4::Profiling::FunctionCallProperties &props = data[dataPos];
+ if (props.start > until)
+ return finalizeMessages(until, messages, props.start);
+
appendMemoryEvents(props.start, messages);
QQmlDebugStream d_start(&message, QIODevice::WriteOnly);
@@ -106,19 +123,30 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
messages.push_back(message);
message.clear();
stack.push(props.end);
- data.pop_front();
+ ++dataPos;
}
- if (stack.empty() && data.empty())
- return appendMemoryEvents(until, messages);
+ if (stack.empty() && dataPos == data.length())
+ return finalizeMessages(until, messages, -1);
}
}
-void QV4ProfilerAdapter::receiveData(const QList<QV4::Profiling::FunctionCallProperties> &new_data,
- const QList<QV4::Profiling::MemoryAllocationProperties> &new_memory_data)
+void QV4ProfilerAdapter::receiveData(
+ const QVector<QV4::Profiling::FunctionCallProperties> &new_data,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &new_memory_data)
{
- data = new_data;
- memory_data = new_memory_data;
- stack.clear();
+ // In rare cases it could be that another flush or stop event is processed while data from
+ // the previous one is still pending. In that case we just append the data.
+
+ if (data.isEmpty())
+ data = new_data;
+ else
+ data.append(new_data);
+
+ if (memory_data.isEmpty())
+ memory_data = new_memory_data;
+ else
+ memory_data.append(new_memory_data);
+
service->dataReady(this);
}
diff --git a/src/qml/debugger/qv4profileradapter_p.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index 2f467f4beb..cea3da72e3 100644
--- a/src/qml/debugger/qv4profileradapter_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -45,8 +45,8 @@
// We mean it.
//
-#include "qv4profiling_p.h"
-#include "qqmlabstractprofileradapter_p.h"
+#include <private/qv4profiling_p.h>
+#include <private/qqmlabstractprofileradapter_p.h>
#include <QStack>
#include <QList>
@@ -63,14 +63,17 @@ public:
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
public slots:
- void receiveData(const QList<QV4::Profiling::FunctionCallProperties> &,
- const QList<QV4::Profiling::MemoryAllocationProperties> &);
+ void receiveData(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private:
- QList<QV4::Profiling::FunctionCallProperties> data;
- QList<QV4::Profiling::MemoryAllocationProperties> memory_data;
+ QVector<QV4::Profiling::FunctionCallProperties> data;
+ QVector<QV4::Profiling::MemoryAllocationProperties> memory_data;
+ int dataPos;
+ int memoryPos;
QStack<qint64> stack;
qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages);
+ qint64 finalizeMessages(qint64 until, QList<QByteArray> &messages, qint64 callNext);
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
deleted file mode 100644
index 2ee0d703b2..0000000000
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
+++ /dev/null
@@ -1,27 +0,0 @@
-TARGET = qmldbg_qtquick2
-QT += qml-private quick-private core-private gui-private
-
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QtQuick2Plugin
-load(qt_plugin)
-
-INCLUDEPATH *= $$PWD $$PWD/../shared
-
-SOURCES += \
- qtquick2plugin.cpp \
- highlight.cpp \
- qquickviewinspector.cpp \
- ../shared/abstracttool.cpp \
- ../shared/abstractviewinspector.cpp \
- inspecttool.cpp
-
-HEADERS += \
- qtquick2plugin.h \
- highlight.h \
- qquickviewinspector.h \
- ../shared/abstracttool.h \
- ../shared/abstractviewinspector.h \
- ../shared/qmlinspectorconstants.h \
- inspecttool.h
-
-OTHER_FILES += qtquick2plugin.json
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
deleted file mode 100644
index 88801ec9db..0000000000
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
+++ /dev/null
@@ -1,78 +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$
-**
-****************************************************************************/
-
-#include "qtquick2plugin.h"
-#include "qquickviewinspector.h"
-
-#include <QtCore/qplugin.h>
-#include <QtQml/private/qqmlinspectorservice_p.h>
-#include <QtQuick/QQuickView>
-
-namespace QmlJSDebugger {
-namespace QtQuick2 {
-
-QtQuick2Plugin::QtQuick2Plugin() :
- m_inspector(0)
-{
-}
-
-QtQuick2Plugin::~QtQuick2Plugin()
-{
- delete m_inspector;
-}
-
-bool QtQuick2Plugin::canHandleView(QObject *view)
-{
- return qobject_cast<QQuickView*>(view);
-}
-
-void QtQuick2Plugin::activate(QObject *view)
-{
- QQuickView *qtQuickView = qobject_cast<QQuickView*>(view);
- Q_ASSERT(qtQuickView);
- m_inspector = new QQuickViewInspector(qtQuickView, qtQuickView);
-}
-
-void QtQuick2Plugin::deactivate()
-{
- delete m_inspector;
-}
-
-void QtQuick2Plugin::clientMessage(const QByteArray &message)
-{
- if (m_inspector)
- m_inspector->handleMessage(message);
-}
-
-} // namespace QtQuick2
-} // namespace QmlJSDebugger
diff --git a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
new file mode 100644
index 0000000000..5e2d0874df
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
@@ -0,0 +1,22 @@
+TARGET = qmldbg_server
+QT = qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlDebugServerFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qqmldebugserver.cpp \
+ $$PWD/../shared/qpacketprotocol.cpp
+
+HEADERS += \
+ $$PWD/qqmldebugserverfactory.h \
+ $$PWD/../shared/qqmldebugserver.h \
+ $$PWD/../shared/qpacketprotocol.h \
+ $$PWD/../shared/qqmldebugserverconnection.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ qqmldebugserver.json
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
new file mode 100644
index 0000000000..1cfebea03c
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -0,0 +1,700 @@
+/****************************************************************************
+**
+** 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 "qqmldebugserver.h"
+#include "qqmldebugserverfactory.h"
+#include "qpacketprotocol.h"
+#include "qqmldebugserverconnection.h"
+
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmlglobal_p.h>
+#include <private/qqmldebugpluginmanager_p.h>
+
+#include <QtCore/QAtomicInt>
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QStringList>
+#include <QtCore/qwaitcondition.h>
+
+#include <private/qobject_p.h>
+#include <private/qcoreapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ QQmlDebug Protocol (Version 1):
+
+ handshake:
+ 1. Client sends
+ "QDeclarativeDebugServer" 0 version pluginNames [QDataStream version]
+ version: an int representing the highest protocol version the client knows
+ pluginNames: plugins available on client side
+ 2. Server sends
+ "QDeclarativeDebugClient" 0 version pluginNames pluginVersions [QDataStream version]
+ version: an int representing the highest protocol version the client & server know
+ pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
+ client plugin advertisement
+ 1. Client sends
+ "QDeclarativeDebugServer" 1 pluginNames
+ server plugin advertisement (not implemented: all services are required to register before open())
+ 1. Server sends
+ "QDeclarativeDebugClient" 1 pluginNames pluginVersions
+ plugin communication:
+ Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
+ */
+
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugServerConnection)
+Q_QML_IMPORT_DEBUG_PLUGIN(QTcpServerConnectionFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QLocalClientConnectionFactory)
+
+const int protocolVersion = 1;
+
+class QQmlDebugServerImpl;
+class QQmlDebugServerThread : public QThread
+{
+public:
+ QQmlDebugServerThread() : m_server(0), m_portFrom(-1), m_portTo(-1) {}
+
+ void setServer(QQmlDebugServerImpl *server)
+ {
+ m_server = server;
+ }
+
+ void setPortRange(int portFrom, int portTo, const QString &hostAddress)
+ {
+ m_pluginName = QLatin1String("QTcpServerConnection");
+ m_portFrom = portFrom;
+ m_portTo = portTo;
+ m_hostAddress = hostAddress;
+ }
+
+ void setFileName(const QString &fileName)
+ {
+ m_pluginName = QLatin1String("QLocalClientConnection");
+ m_fileName = fileName;
+ }
+
+ void run();
+
+private:
+ QQmlDebugServerImpl *m_server;
+ QString m_pluginName;
+ int m_portFrom;
+ int m_portTo;
+ bool m_block;
+ QString m_hostAddress;
+ QString m_fileName;
+};
+
+class QQmlDebugServerImpl : public QQmlDebugServer
+{
+ Q_OBJECT
+public:
+ QQmlDebugServerImpl();
+
+ bool blockingMode() const;
+
+ QQmlDebugService *service(const QString &name) const;
+
+ void addEngine(QQmlEngine *engine);
+ void removeEngine(QQmlEngine *engine);
+
+ bool addService(const QString &name, QQmlDebugService *service);
+ bool removeService(const QString &name);
+
+ bool open(const QVariantHash &configuration);
+ void setDevice(QIODevice *socket);
+
+ void parseArguments();
+
+ static void cleanup();
+
+private slots:
+ void wakeEngine(QQmlEngine *engine);
+ void sendMessage(const QString &name, const QByteArray &message);
+ void sendMessages(const QString &name, const QList<QByteArray> &messages);
+ void changeServiceState(const QString &serviceName, QQmlDebugService::State state);
+ void removeThread();
+ void receiveMessage();
+ void invalidPacket();
+
+private:
+ friend class QQmlDebugServerThread;
+ friend class QQmlDebugServerFactory;
+
+ class EngineCondition {
+ public:
+ EngineCondition() : numServices(0), condition(new QWaitCondition) {}
+
+ bool waitForServices(QMutex *locked, int numEngines);
+
+ void wake();
+ private:
+ int numServices;
+
+ // shared pointer to allow for QHash-inflicted copying.
+ QSharedPointer<QWaitCondition> condition;
+ };
+
+ bool canSendMessage(const QString &name);
+ void doSendMessage(const QString &name, const QByteArray &message);
+
+ QQmlDebugServerConnection *m_connection;
+ QHash<QString, QQmlDebugService *> m_plugins;
+ QStringList m_clientPlugins;
+ bool m_gotHello;
+ bool m_blockingMode;
+
+ QHash<QQmlEngine *, EngineCondition> m_engineConditions;
+
+ QMutex m_helloMutex;
+ QWaitCondition m_helloCondition;
+ QQmlDebugServerThread m_thread;
+ QPacketProtocol *m_protocol;
+ QAtomicInt m_changeServiceStateCalls;
+};
+
+void QQmlDebugServerImpl::cleanup()
+{
+ QQmlDebugServerImpl *server = static_cast<QQmlDebugServerImpl *>(
+ QQmlDebugConnector::instance());
+ if (!server)
+ return;
+
+ for (QHash<QString, QQmlDebugService *>::ConstIterator i = server->m_plugins.constBegin();
+ i != server->m_plugins.constEnd(); ++i) {
+ server->m_changeServiceStateCalls.ref();
+ QMetaObject::invokeMethod(server, "changeServiceState", Qt::QueuedConnection,
+ Q_ARG(QString, i.key()),
+ Q_ARG(QQmlDebugService::State,
+ QQmlDebugService::NotConnected));
+ }
+
+ // Wait for changeServiceState calls to finish
+ // (while running an event loop because some services
+ // might again use slots to execute stuff in the GUI thread)
+ QEventLoop loop;
+ while (!server->m_changeServiceStateCalls.testAndSetOrdered(0, 0))
+ loop.processEvents();
+
+ // Stop the thread while the application is still there.
+ server->m_thread.exit();
+ server->m_thread.wait();
+}
+
+void QQmlDebugServerThread::run()
+{
+ Q_ASSERT_X(m_server != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
+ QQmlDebugServerConnection *connection = loadQQmlDebugServerConnection(m_pluginName);
+ if (connection) {
+ connection->setServer(m_server);
+
+ if (m_fileName.isEmpty()) {
+ if (!connection->setPortRange(m_portFrom, m_portTo, m_server->blockingMode(),
+ m_hostAddress)) {
+ delete connection;
+ return;
+ }
+ } else {
+ if (!connection->setFileName(m_fileName, m_server->blockingMode())) {
+ delete connection;
+ return;
+ }
+ }
+
+ {
+ QMutexLocker connectionLocker(&m_server->m_helloMutex);
+ m_server->m_connection = connection;
+ m_server->m_helloCondition.wakeAll();
+ }
+
+ if (m_server->blockingMode())
+ connection->waitForConnection();
+ } else {
+ qWarning() << "QML Debugger: Couldn't load plugin" << m_pluginName;
+ return;
+ }
+
+ exec();
+
+ // make sure events still waiting are processed
+ QEventLoop eventLoop;
+ eventLoop.processEvents(QEventLoop::AllEvents);
+}
+
+bool QQmlDebugServerImpl::blockingMode() const
+{
+ return m_blockingMode;
+}
+
+static void cleanupOnShutdown()
+{
+ // We cannot do this in the destructor as the connection plugin will get unloaded before the
+ // server plugin and we need the connection to send any remaining data. This function is
+ // triggered before any plugins are unloaded.
+ QQmlDebugServerImpl::cleanup();
+}
+
+QQmlDebugServerImpl::QQmlDebugServerImpl() :
+ m_connection(0),
+ m_gotHello(false),
+ m_blockingMode(false)
+{
+ static bool postRoutineAdded = false;
+ if (!postRoutineAdded) {
+ qAddPostRoutine(cleanupOnShutdown);
+ postRoutineAdded = true;
+ }
+
+ // used in sendMessages
+ qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
+ // used in changeServiceState
+ qRegisterMetaType<QQmlDebugService::State>("QQmlDebugService::State");
+
+ m_thread.setServer(this);
+ moveToThread(&m_thread);
+
+ // Remove the thread immmediately when it finishes, so that we don't have to wait for the
+ // event loop to signal that.
+ QObject::connect(&m_thread, SIGNAL(finished()), this, SLOT(removeThread()),
+ Qt::DirectConnection);
+ m_thread.setObjectName(QStringLiteral("QQmlDebugServerThread"));
+ parseArguments();
+}
+
+bool QQmlDebugServerImpl::open(const QVariantHash &configuration = QVariantHash())
+{
+ if (m_thread.isRunning())
+ return false;
+ if (!configuration.isEmpty()) {
+ m_blockingMode = configuration[QLatin1String("block")].toBool();
+ if (configuration.contains(QLatin1String("portFrom"))) {
+ int portFrom = configuration[QLatin1String("portFrom")].toInt();
+ int portTo = configuration[QLatin1String("portTo")].toInt();
+ m_thread.setPortRange(portFrom, portTo == -1 ? portFrom : portTo,
+ configuration[QLatin1String("hostAddress")].toString());
+ } else if (configuration.contains(QLatin1String("fileName"))) {
+ m_thread.setFileName(configuration[QLatin1String("fileName")].toString());
+ } else {
+ return false;
+ }
+ }
+
+ QMutexLocker locker(&m_helloMutex);
+ m_thread.start();
+ m_helloCondition.wait(&m_helloMutex); // wait for connection
+ if (m_blockingMode && !m_gotHello)
+ m_helloCondition.wait(&m_helloMutex); // wait for hello
+ return true;
+}
+
+void QQmlDebugServerImpl::parseArguments()
+{
+ // format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
+ const QString args = commandLineArguments();
+ if (args.isEmpty())
+ return; // Manual initialization, through QQmlDebugServer::open()
+
+ // ### remove port definition when protocol is changed
+ int portFrom = 0;
+ int portTo = 0;
+ bool block = false;
+ bool ok = false;
+ QString hostAddress;
+ QString fileName;
+ QStringList services;
+
+ const QStringList lstjsDebugArguments = args.split(QLatin1Char(','));
+ 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:"))) {
+ portFrom = strArgument.mid(5).toInt(&ok);
+ portTo = portFrom;
+ QStringList::const_iterator argsNext = argsIt + 1;
+ if (argsNext == argsItEnd)
+ break;
+ const QString nextArgument = *argsNext;
+
+ // Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly
+ // shared copy of the passed string. That copy isn't properly detached when the library
+ // is unloaded if the original string lives in the library's .rodata
+ if (ok && nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) {
+ portTo = nextArgument.toInt(&ok);
+ ++argsIt;
+ }
+ } else if (strArgument.startsWith(QLatin1String("host:"))) {
+ hostAddress = strArgument.mid(5);
+ } else if (strArgument == QLatin1String("block")) {
+ block = true;
+ } else if (strArgument.startsWith(QLatin1String("file:"))) {
+ fileName = strArgument.mid(5);
+ ok = !fileName.isEmpty();
+ } else if (strArgument.startsWith(QLatin1String("services:"))) {
+ services.append(strArgument.mid(9));
+ } else if (!services.isEmpty()) {
+ services.append(strArgument);
+ } else {
+ qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
+ "detected. Ignoring the same.")
+ .arg(strArgument);
+ }
+ }
+
+ if (ok) {
+ setServices(services);
+ m_blockingMode = block;
+ if (!fileName.isEmpty())
+ m_thread.setFileName(fileName);
+ else
+ m_thread.setPortRange(portFrom, portTo, hostAddress);
+ } else {
+ qWarning() << QString::fromLatin1("QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
+ "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
+ "<ip address>][,block]").arg(args);
+ }
+}
+
+void QQmlDebugServerImpl::receiveMessage()
+{
+ typedef QHash<QString, QQmlDebugService*>::const_iterator DebugServiceConstIt;
+
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ if (!m_protocol)
+ return;
+
+ QQmlDebugStream in(m_protocol->read().data());
+
+ QString name;
+
+ in >> name;
+ if (name == QLatin1String("QDeclarativeDebugServer")) {
+ int op = -1;
+ in >> op;
+ if (op == 0) {
+ int version;
+ in >> version >> m_clientPlugins;
+
+ //Get the supported QDataStream version
+ if (!in.atEnd()) {
+ in >> QQmlDebugStream::s_dataStreamVersion;
+ if (QQmlDebugStream::s_dataStreamVersion > QDataStream().version())
+ QQmlDebugStream::s_dataStreamVersion = QDataStream().version();
+ }
+
+ // Send the hello answer immediately, since it needs to arrive before
+ // the plugins below start sending messages.
+
+ QByteArray helloAnswer;
+ QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ const int count = m_plugins.count();
+ pluginNames.reserve(count);
+ pluginVersions.reserve(count);
+ for (QHash<QString, QQmlDebugService *>::ConstIterator i = m_plugins.constBegin();
+ i != m_plugins.constEnd(); ++i) {
+ pluginNames << i.key();
+ pluginVersions << i.value()->version();
+ }
+
+ out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
+ << pluginNames << pluginVersions << QQmlDebugStream::s_dataStreamVersion;
+
+ QPacket pack;
+ pack.writeRawData(helloAnswer.data(), helloAnswer.length());
+ m_protocol->send(pack);
+ m_connection->flush();
+
+ QMutexLocker helloLock(&m_helloMutex);
+ m_gotHello = true;
+
+ for (DebugServiceConstIt iter = m_plugins.constBegin(), cend = m_plugins.constEnd(); iter != cend; ++iter) {
+ QQmlDebugService::State newState = QQmlDebugService::Unavailable;
+ if (m_clientPlugins.contains(iter.key()))
+ newState = QQmlDebugService::Enabled;
+ m_changeServiceStateCalls.ref();
+ changeServiceState(iter.key(), newState);
+ }
+
+ m_helloCondition.wakeAll();
+
+ } else if (op == 1) {
+ // Service Discovery
+ QStringList oldClientPlugins = m_clientPlugins;
+ in >> m_clientPlugins;
+
+ for (DebugServiceConstIt iter = m_plugins.constBegin(), cend = m_plugins.constEnd(); iter != cend; ++iter) {
+ const QString pluginName = iter.key();
+ QQmlDebugService::State newState = QQmlDebugService::Unavailable;
+ if (m_clientPlugins.contains(pluginName))
+ newState = QQmlDebugService::Enabled;
+
+ if (oldClientPlugins.contains(pluginName)
+ != m_clientPlugins.contains(pluginName)) {
+ m_changeServiceStateCalls.ref();
+ changeServiceState(iter.key(), newState);
+ }
+ }
+
+ } else {
+ qWarning("QML Debugger: Invalid control message %d.", op);
+ invalidPacket();
+ return;
+ }
+
+ } else {
+ if (m_gotHello) {
+ QByteArray message;
+ in >> message;
+
+ QHash<QString, QQmlDebugService *>::Iterator iter = m_plugins.find(name);
+ if (iter == m_plugins.end()) {
+ qWarning() << "QML Debugger: Message received for missing plugin" << name << '.';
+ } else {
+ (*iter)->messageReceived(message);
+ }
+ } else {
+ qWarning("QML Debugger: Invalid hello message.");
+ }
+
+ }
+}
+
+void QQmlDebugServerImpl::changeServiceState(const QString &serviceName,
+ QQmlDebugService::State newState)
+{
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ QQmlDebugService *service = m_plugins.value(serviceName);
+ if (service && service->state() != newState) {
+ service->stateAboutToBeChanged(newState);
+ service->setState(newState);
+ service->stateChanged(newState);
+ }
+
+ m_changeServiceStateCalls.deref();
+}
+
+void QQmlDebugServerImpl::removeThread()
+{
+ Q_ASSERT(m_thread.isFinished());
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ QThread *parentThread = m_thread.thread();
+
+ delete m_connection;
+ m_connection = 0;
+
+ // Move it back to the parent thread so that we can potentially restart it on a new thread.
+ moveToThread(parentThread);
+}
+
+QQmlDebugService *QQmlDebugServerImpl::service(const QString &name) const
+{
+ return m_plugins.value(name);
+}
+
+void QQmlDebugServerImpl::addEngine(QQmlEngine *engine)
+{
+ // to be executed outside of debugger thread
+ Q_ASSERT(QThread::currentThread() != &m_thread);
+
+ QMutexLocker locker(&m_helloMutex);
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineAboutToBeAdded(engine);
+
+ m_engineConditions[engine].waitForServices(&m_helloMutex, m_plugins.count());
+
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineAdded(engine);
+}
+
+void QQmlDebugServerImpl::removeEngine(QQmlEngine *engine)
+{
+ // to be executed outside of debugger thread
+ Q_ASSERT(QThread::currentThread() != &m_thread);
+
+ QMutexLocker locker(&m_helloMutex);
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineAboutToBeRemoved(engine);
+
+ m_engineConditions[engine].waitForServices(&m_helloMutex, m_plugins.count());
+
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineRemoved(engine);
+}
+
+bool QQmlDebugServerImpl::addService(const QString &name, QQmlDebugService *service)
+{
+ // to be executed before thread starts
+ Q_ASSERT(!m_thread.isRunning());
+
+ if (!service || m_plugins.contains(name))
+ return false;
+
+ connect(service, SIGNAL(messageToClient(QString,QByteArray)),
+ this, SLOT(sendMessage(QString,QByteArray)));
+ connect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
+ this, SLOT(sendMessages(QString,QList<QByteArray>)));
+
+ connect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
+ connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
+
+ service->setState(QQmlDebugService::Unavailable);
+ m_plugins.insert(name, service);
+
+ return true;
+}
+
+bool QQmlDebugServerImpl::removeService(const QString &name)
+{
+ // to be executed after thread ends
+ Q_ASSERT(!m_thread.isRunning());
+
+ QQmlDebugService *service = m_plugins.value(name);
+ if (!service)
+ return false;
+
+ m_plugins.remove(name);
+ service->setState(QQmlDebugService::NotConnected);
+
+ disconnect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)));
+ disconnect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)));
+
+ disconnect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
+ this, SLOT(sendMessages(QString,QList<QByteArray>)));
+ disconnect(service, SIGNAL(messageToClient(QString,QByteArray)),
+ this, SLOT(sendMessage(QString,QByteArray)));
+
+ m_plugins.remove(service->name());
+
+ return true;
+}
+
+bool QQmlDebugServerImpl::canSendMessage(const QString &name)
+{
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+ return m_connection && m_connection->isConnected() && m_protocol &&
+ m_clientPlugins.contains(name);
+}
+
+void QQmlDebugServerImpl::doSendMessage(const QString &name, const QByteArray &message)
+{
+ QByteArray prefixed;
+ QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
+ out << name << message;
+
+ QPacket pack;
+ pack.writeRawData(prefixed.data(), prefixed.length());
+ m_protocol->send(pack);
+}
+
+void QQmlDebugServerImpl::sendMessage(const QString &name, const QByteArray &message)
+{
+ if (canSendMessage(name)) {
+ doSendMessage(name, message);
+ m_connection->flush();
+ }
+}
+
+void QQmlDebugServerImpl::sendMessages(const QString &name, const QList<QByteArray> &messages)
+{
+ if (canSendMessage(name)) {
+ foreach (const QByteArray &message, messages)
+ doSendMessage(name, message);
+ m_connection->flush();
+ }
+}
+
+void QQmlDebugServerImpl::wakeEngine(QQmlEngine *engine)
+{
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ QMutexLocker locker(&m_helloMutex);
+ m_engineConditions[engine].wake();
+}
+
+bool QQmlDebugServerImpl::EngineCondition::waitForServices(QMutex *locked, int num)
+{
+ Q_ASSERT_X(numServices == 0, Q_FUNC_INFO, "Request to wait again before previous wait finished");
+ numServices = num;
+ return numServices > 0 ? condition->wait(locked) : true;
+}
+
+void QQmlDebugServerImpl::EngineCondition::wake()
+{
+ if (--numServices == 0)
+ condition->wakeAll();
+ Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services.");
+}
+
+void QQmlDebugServerImpl::setDevice(QIODevice *socket)
+{
+ m_protocol = new QPacketProtocol(socket, this);
+ QObject::connect(m_protocol, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
+ QObject::connect(m_protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket()));
+
+ if (blockingMode())
+ m_protocol->waitForReadyRead(-1);
+}
+
+void QQmlDebugServerImpl::invalidPacket()
+{
+ qWarning("QML Debugger: Received a corrupted packet! Giving up ...");
+ m_connection->disconnect();
+ // protocol might still be processing packages at this point
+ m_protocol->deleteLater();
+ m_protocol = 0;
+}
+
+QQmlDebugConnector *QQmlDebugServerFactory::create(const QString &key)
+{
+ // Cannot parent it to this because it gets moved to another thread
+ return (key == QLatin1String("QQmlDebugServer") ? new QQmlDebugServerImpl : 0);
+}
+
+QT_END_NAMESPACE
+
+#include "qqmldebugserver.moc"
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json
new file mode 100644
index 0000000000..9b8dd3ae79
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QQmlDebugServer" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h b/src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h
new file mode 100644
index 0000000000..825a71bab8
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGSERVERFACTORY_H
+#define QQMLDEBUGSERVERFACTORY_H
+
+#include <private/qqmldebugconnector_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// ementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugServerFactory : public QQmlDebugConnectorFactory
+{
+ Q_OBJECT
+
+ // The interface for the code that loads this thing is QQmlDebugConnector.
+ // QQmlDebugServer is for connection plugins.
+ Q_PLUGIN_METADATA(IID QQmlDebugConnectorFactory_iid FILE "qqmldebugserver.json")
+public:
+ QQmlDebugConnector *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGSERVERFACTORY_H
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri
deleted file mode 100644
index 4b78707c3d..0000000000
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri
+++ /dev/null
@@ -1,14 +0,0 @@
-QT += network core-private
-
-SOURCES += \
- $$PWD/qtcpserverconnection.cpp \
- $$PWD/../shared/qpacketprotocol.cpp
-
-HEADERS += \
- $$PWD/qtcpserverconnection.h \
- $$PWD/../shared/qpacketprotocol.h
-
-INCLUDEPATH += $$PWD \
- $$PWD/../shared
-
-OTHER_FILES += $$PWD/qtcpserverconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
index e1284b7233..fd419aeb56 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
+++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
@@ -1,8 +1,20 @@
TARGET = qmldbg_tcp
-QT = qml-private core-private
+QT = qml-private network
PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QTcpServerConnection
+PLUGIN_CLASS_NAME = QTcpServerConnectionFactory
load(qt_plugin)
-include(qmldbg_tcp.pri)
+SOURCES += \
+ $$PWD/qtcpserverconnection.cpp
+
+HEADERS += \
+ $$PWD/qtcpserverconnectionfactory.h \
+ $$PWD/../shared/qqmldebugserver.h \
+ $$PWD/../shared/qqmldebugserverconnection.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qtcpserverconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 2ae4edfce4..c8010a4aa9 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -31,136 +31,125 @@
**
****************************************************************************/
-#include "qtcpserverconnection.h"
-#include "qpacketprotocol.h"
+#include "qtcpserverconnectionfactory.h"
+#include "qqmldebugserver.h"
#include <QtCore/qplugin.h>
#include <QtNetwork/qtcpserver.h>
#include <QtNetwork/qtcpsocket.h>
-#include <private/qqmldebugserver_p.h>
-
QT_BEGIN_NAMESPACE
-class QTcpServerConnectionPrivate {
+class QTcpServerConnection : public QQmlDebugServerConnection
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QTcpServerConnection)
+
public:
- QTcpServerConnectionPrivate();
+ QTcpServerConnection();
+ ~QTcpServerConnection();
- int portFrom;
- int portTo;
- bool block;
- QString hostaddress;
- QTcpSocket *socket;
- QPacketProtocol *protocol;
- QTcpServer *tcpServer;
+ void setServer(QQmlDebugServer *server);
+ bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress);
+ bool setFileName(const QString &fileName, bool block);
- QQmlDebugServer *debugServer;
-};
+ bool isConnected() const;
+ void disconnect();
-QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() :
- portFrom(0),
- portTo(0),
- block(false),
- socket(0),
- protocol(0),
- tcpServer(0),
- debugServer(0)
-{
-}
+ void waitForConnection();
+ void flush();
+
+private slots:
+ void newConnection();
+
+private:
+ bool listen();
+
+ int m_portFrom;
+ int m_portTo;
+ bool m_block;
+ QString m_hostaddress;
+ QTcpSocket *m_socket;
+ QTcpServer *m_tcpServer;
+ QQmlDebugServer *m_debugServer;
+};
QTcpServerConnection::QTcpServerConnection() :
- d_ptr(new QTcpServerConnectionPrivate)
+ m_portFrom(0),
+ m_portTo(0),
+ m_block(false),
+ m_socket(0),
+ m_tcpServer(0),
+ m_debugServer(0)
{
-
}
QTcpServerConnection::~QTcpServerConnection()
{
if (isConnected())
disconnect();
- delete d_ptr;
}
void QTcpServerConnection::setServer(QQmlDebugServer *server)
{
- Q_D(QTcpServerConnection);
- d->debugServer = server;
+ m_debugServer = server;
}
bool QTcpServerConnection::isConnected() const
{
- Q_D(const QTcpServerConnection);
- return d->socket && d->socket->state() == QTcpSocket::ConnectedState;
-}
-
-void QTcpServerConnection::send(const QList<QByteArray> &messages)
-{
- Q_D(QTcpServerConnection);
-
- 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();
+ return m_socket && m_socket->state() == QTcpSocket::ConnectedState;
}
void QTcpServerConnection::disconnect()
{
- Q_D(QTcpServerConnection);
-
- while (d->socket && d->socket->bytesToWrite() > 0) {
- if (!d->socket->waitForBytesWritten()) {
+ while (m_socket && m_socket->bytesToWrite() > 0) {
+ if (!m_socket->waitForBytesWritten()) {
qWarning("QML Debugger: Failed to send remaining %lld bytes on disconnect.",
- d->socket->bytesToWrite());
+ m_socket->bytesToWrite());
break;
}
}
- // protocol might still be processing packages at this point
- d->protocol->deleteLater();
- d->protocol = 0;
- d->socket->deleteLater();
- d->socket = 0;
-}
-
-bool QTcpServerConnection::waitForMessage()
-{
- Q_D(QTcpServerConnection);
- return d->protocol->waitForReadyRead(-1);
+ m_socket->deleteLater();
+ m_socket = 0;
}
bool QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block,
const QString &hostaddress)
{
- Q_D(QTcpServerConnection);
- d->portFrom = portFrom;
- d->portTo = portTo;
- d->block = block;
- d->hostaddress = hostaddress;
+ m_portFrom = portFrom;
+ m_portTo = portTo;
+ m_block = block;
+ m_hostaddress = hostaddress;
return listen();
}
+bool QTcpServerConnection::setFileName(const QString &fileName, bool block)
+{
+ Q_UNUSED(fileName);
+ Q_UNUSED(block);
+ return false;
+}
+
void QTcpServerConnection::waitForConnection()
{
- Q_D(QTcpServerConnection);
- d->tcpServer->waitForNewConnection(-1);
+ m_tcpServer->waitForNewConnection(-1);
}
-bool QTcpServerConnection::listen()
+void QTcpServerConnection::flush()
{
- Q_D(QTcpServerConnection);
+ if (m_socket)
+ m_socket->flush();
+}
- d->tcpServer = new QTcpServer(this);
- QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
+bool QTcpServerConnection::listen()
+{
+ m_tcpServer = new QTcpServer(this);
+ QObject::connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
QHostAddress hostaddress;
- if (!d->hostaddress.isEmpty()) {
- if (!hostaddress.setAddress(d->hostaddress)) {
+ if (!m_hostaddress.isEmpty()) {
+ if (!hostaddress.setAddress(m_hostaddress)) {
hostaddress = QHostAddress::Any;
qDebug("QML Debugger: Incorrect host address provided. So accepting connections "
"from any host.");
@@ -168,64 +157,45 @@ bool QTcpServerConnection::listen()
} else {
hostaddress = QHostAddress::Any;
}
- int port = d->portFrom;
+ int port = m_portFrom;
do {
- if (d->tcpServer->listen(hostaddress, port)) {
+ if (m_tcpServer->listen(hostaddress, port)) {
qDebug("QML Debugger: Waiting for connection on port %d...", port);
break;
}
++port;
- } while (port <= d->portTo);
- if (port > d->portTo) {
- if (d->portFrom == d->portTo)
- qWarning("QML Debugger: Unable to listen to port %d.", d->portFrom);
+ } while (port <= m_portTo);
+ if (port > m_portTo) {
+ if (m_portFrom == m_portTo)
+ qWarning("QML Debugger: Unable to listen to port %d.", m_portFrom);
else
- qWarning("QML Debugger: Unable to listen to ports %d - %d.", d->portFrom, d->portTo);
+ qWarning("QML Debugger: Unable to listen to ports %d - %d.", m_portFrom, m_portTo);
return false;
} else {
return true;
}
}
-
-void QTcpServerConnection::readyRead()
-{
- Q_D(QTcpServerConnection);
- if (!d->protocol)
- return;
-
- QPacket packet = d->protocol->read();
-
- QByteArray content = packet.data();
- d->debugServer->receiveMessage(content);
-}
-
void QTcpServerConnection::newConnection()
{
- Q_D(QTcpServerConnection);
-
- if (d->socket && d->socket->peerPort()) {
+ if (m_socket && m_socket->peerPort()) {
qWarning("QML Debugger: Another client is already connected.");
- QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection();
+ QTcpSocket *faultyConnection = m_tcpServer->nextPendingConnection();
delete faultyConnection;
return;
}
- delete d->socket;
- d->socket = d->tcpServer->nextPendingConnection();
- d->socket->setParent(this);
- 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);
- }
+ delete m_socket;
+ m_socket = m_tcpServer->nextPendingConnection();
+ m_socket->setParent(this);
+ m_debugServer->setDevice(m_socket);
}
-void QTcpServerConnection::invalidPacket()
+QQmlDebugServerConnection *QTcpServerConnectionFactory::create(const QString &key)
{
- qWarning("QML Debugger: Received a corrupted packet! Giving up ...");
+ return (key == QLatin1String("QTcpServerConnection") ? new QTcpServerConnection : 0);
}
QT_END_NAMESPACE
+
+#include "qtcpserverconnection.moc"
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json
new file mode 100644
index 0000000000..201a1b3fcb
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QTcpServerConnection" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h
new file mode 100644
index 0000000000..97dde03087
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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 QTCPSERVERCONNECTIONFACTORY_H
+#define QTCPSERVERCONNECTIONFACTORY_H
+
+#include "qqmldebugserverconnection.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTcpServerConnectionFactory : public QQmlDebugServerConnectionFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServerConnectionFactory_iid FILE "qtcpserverconnection.json")
+ Q_INTERFACES(QQmlDebugServerConnectionFactory)
+public:
+ QQmlDebugServerConnection *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QTCPSERVERCONNECTIONFACTORY_H
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 3bc48a6b33..ae13826a4c 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,4 +1,10 @@
TEMPLATE = subdirs
-SUBDIRS = qmldbg_tcp
-qtHaveModule(quick): SUBDIRS += qmldbg_qtquick2
+SUBDIRS += \
+ qmldbg_debugger \
+ qmldbg_local \
+ qmldbg_profiler \
+ qmldbg_server \
+ qmldbg_tcp
+
+qtHaveModule(quick): SUBDIRS += qmldbg_inspector
diff --git a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
new file mode 100644
index 0000000000..9aa4531428
--- /dev/null
+++ b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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 QQMLCONFIGURABLEDEBUGSEVICE_H
+#define QQMLCONFIGURABLEDEBUGSEVICE_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/qqmldebugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+template <class Base>
+class QQmlConfigurableDebugService : public Base
+{
+protected:
+ QQmlConfigurableDebugService(float version, QObject *parent = 0) :
+ Base(version, parent), m_configMutex(QMutex::Recursive)
+ {
+ init();
+ }
+
+ void stopWaiting()
+ {
+ QMutexLocker lock(&m_configMutex);
+ m_waitingForConfiguration = false;
+ foreach (QQmlEngine *engine, m_waitingEngines)
+ emit Base::attachedToEngine(engine);
+ m_waitingEngines.clear();
+ }
+
+ void init()
+ {
+ QMutexLocker lock(&m_configMutex);
+ // If we're not enabled or not blocking, don't wait for configuration
+ m_waitingForConfiguration = (Base::state() == QQmlDebugService::Enabled &&
+ QQmlDebugConnector::instance()->blockingMode());
+ }
+
+ void stateChanged(QQmlDebugService::State newState)
+ {
+ if (newState != QQmlDebugService::Enabled)
+ stopWaiting();
+ else
+ init();
+ }
+
+ void engineAboutToBeAdded(QQmlEngine *engine)
+ {
+ QMutexLocker lock(&m_configMutex);
+ if (m_waitingForConfiguration)
+ m_waitingEngines.append(engine);
+ else
+ emit Base::attachedToEngine(engine);
+ }
+
+ QMutex m_configMutex;
+ QList<QQmlEngine *> m_waitingEngines;
+ bool m_waitingForConfiguration;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLCONFIGURABLEDEBUGSEVICE_H
diff --git a/src/plugins/qmltooling/shared/qqmldebugserver.h b/src/plugins/qmltooling/shared/qqmldebugserver.h
new file mode 100644
index 0000000000..a7c17075d9
--- /dev/null
+++ b/src/plugins/qmltooling/shared/qqmldebugserver.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGSERVER_H
+#define QQMLDEBUGSERVER_H
+
+#include <private/qqmldebugconnector_p.h>
+#include <private/qtqmlglobal_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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugServer : protected QQmlDebugConnector
+{
+ Q_OBJECT
+public:
+ virtual void setDevice(QIODevice *socket) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGSERVER_H
diff --git a/src/qml/debugger/qqmldebugserverconnection_p.h b/src/plugins/qmltooling/shared/qqmldebugserverconnection.h
index 9170238b46..9bdb1bcc8b 100644
--- a/src/qml/debugger/qqmldebugserverconnection_p.h
+++ b/src/plugins/qmltooling/shared/qqmldebugserverconnection.h
@@ -34,8 +34,8 @@
#ifndef QQMLDEBUGSERVERCONNECTION_H
#define QQMLDEBUGSERVERCONNECTION_H
-#include <QtQml/qtqmlglobal.h>
-#include <private/qqmlglobal_p.h>
+#include <private/qtqmlglobal_p.h>
+#include <QtCore/qobject.h>
//
// W A R N I N G
@@ -52,24 +52,30 @@ QT_BEGIN_NAMESPACE
class QQmlDebugServer;
-class Q_QML_PRIVATE_EXPORT QQmlDebugServerConnection
+class QQmlDebugServerConnection : public QObject
{
+ Q_OBJECT
public:
- QQmlDebugServerConnection() {}
- virtual ~QQmlDebugServerConnection() {}
+ QQmlDebugServerConnection(QObject *parent = 0) : QObject(parent) {}
virtual void setServer(QQmlDebugServer *server) = 0;
- virtual bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress) = 0;
+ virtual bool setPortRange(int portFrom, int portTo, bool block, 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;
virtual void waitForConnection() = 0;
- virtual bool waitForMessage() = 0;
+ virtual void flush() = 0;
};
-#define QQmlDebugServerConnection_iid "org.qt-project.Qt.QQmlDebugServerConnection"
+class QQmlDebugServerConnectionFactory : public QObject
+{
+ Q_OBJECT
+public:
+ virtual QQmlDebugServerConnection *create(const QString &key) = 0;
+};
-Q_DECLARE_INTERFACE(QQmlDebugServerConnection, QQmlDebugServerConnection_iid)
+#define QQmlDebugServerConnectionFactory_iid "org.qt-project.Qt.QQmlDebugServerConnectionFactory"
+Q_DECLARE_INTERFACE(QQmlDebugServerConnectionFactory, QQmlDebugServerConnectionFactory_iid)
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 63833504f1..4b1e3601dc 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>
@@ -1456,10 +1456,8 @@ JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR
, _disableAcceleratedLookups(false)
, _contextObject(0)
, _scopeObject(0)
- , _contextObjectTemp(-1)
- , _scopeObjectTemp(-1)
+ , _qmlContextTemp(-1)
, _importedScriptsTemp(-1)
- , _idArrayTemp(-1)
{
_module = jsModule;
_module->setFileName(fileName);
@@ -1764,24 +1762,14 @@ static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver,
void JSCodeGen::beginFunctionBodyHook()
{
- _contextObjectTemp = _block->newTemp();
- _scopeObjectTemp = _block->newTemp();
+ _qmlContextTemp = _block->newTemp();
_importedScriptsTemp = _block->newTemp();
- _idArrayTemp = _block->newTemp();
#ifndef V4_BOOTSTRAP
- QV4::IR::Temp *temp = _block->TEMP(_contextObjectTemp);
- temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
- initMetaObjectResolver(temp->memberResolver, _contextObject);
- move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context_object, 0, 0));
-
- temp = _block->TEMP(_scopeObjectTemp);
- temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
- initMetaObjectResolver(temp->memberResolver, _scopeObject);
- move(temp, _block->NAME(QV4::IR::Name::builtin_qml_scope_object, 0, 0));
+ QV4::IR::Temp *temp = _block->TEMP(_qmlContextTemp);
+ move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context, 0, 0));
move(_block->TEMP(_importedScriptsTemp), _block->NAME(QV4::IR::Name::builtin_qml_imported_scripts_object, 0, 0));
- move(_block->TEMP(_idArrayTemp), _block->NAME(QV4::IR::Name::builtin_qml_id_array, 0, 0));
#endif
}
@@ -1807,7 +1795,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
foreach (const IdMapping &mapping, _idObjects)
if (name == mapping.name) {
_function->idObjectDependencies.insert(mapping.idIndex);
- QV4::IR::Expr *s = subscript(_block->TEMP(_idArrayTemp), _block->CONST(QV4::IR::SInt32Type, mapping.idIndex));
+ QV4::IR::Expr *s = _block->MEMBER(_block->TEMP(_qmlContextTemp), _function->newString(name), 0, QV4::IR::Member::MemberOfIdObjectsArray, mapping.idIndex);
QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
_block->MOVE(result, s);
result = _block->TEMP(result->index);
@@ -1857,7 +1845,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- QV4::IR::Temp *base = _block->TEMP(_scopeObjectTemp);
+ QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
initMetaObjectResolver(base->memberResolver, _scopeObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject);
@@ -1870,7 +1858,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- QV4::IR::Temp *base = _block->TEMP(_contextObjectTemp);
+ QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
initMetaObjectResolver(base->memberResolver, _contextObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlContextObject);
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 120de91321..5617912081 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -34,7 +34,6 @@
#define QQMLIRBUILDER_P_H
#include <private/qqmljsast_p.h>
-#include <private/qqmlpool_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compileddata_p.h>
@@ -496,10 +495,8 @@ private:
ObjectIdMapping _idObjects;
QQmlPropertyCache *_contextObject;
QQmlPropertyCache *_scopeObject;
- int _contextObjectTemp;
- int _scopeObjectTemp;
+ int _qmlContextTemp;
int _importedScriptsTemp;
- int _idArrayTemp;
};
} // namespace QmlIR
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 4e9817aa0d..80aa617c53 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) {
@@ -780,15 +780,18 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
int propertyIdx = 0;
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
- if (p->type == QV4::CompiledData::Property::Alias ||
- p->type == QV4::CompiledData::Property::Var)
+ if (p->type == QV4::CompiledData::Property::Alias)
continue;
int propertyType = 0;
int vmePropertyType = 0;
quint32 propertyFlags = 0;
- if (p->type < builtinTypeCount) {
+ if (p->type == QV4::CompiledData::Property::Var) {
+ propertyType = QMetaType::QVariant;
+ vmePropertyType = QQmlVMEMetaData::VarPropertyType;
+ propertyFlags = QQmlPropertyData::IsVarProperty;
+ } else if (p->type < builtinTypeCount) {
propertyType = builtinTypes[p->type].metaType;
vmePropertyType = propertyType;
@@ -852,30 +855,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
vmd->propertyCount++;
}
- // Now do var properties
- propertyIdx = 0;
- for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
-
- if (p->type != QV4::CompiledData::Property::Var)
- continue;
-
- quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
- if (!(p->flags & QV4::CompiledData::Property::IsReadOnly))
- propertyFlags |= QQmlPropertyData::IsWritable;
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
- vmd->propertyCount++;
- ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
-
- QString propertyName = stringAt(p->nameIndex);
- if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- QMetaType::QVariant, effectiveSignalIndex);
-
- effectiveSignalIndex++;
- }
-
// Alias property count. Actual data is setup in buildDynamicMetaAliases
((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
@@ -1022,10 +1001,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()) {
@@ -2017,7 +1996,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
customParserBindingsPerObject->insert(objectIndex, customParserBindings);
const QList<QQmlError> parserErrors = customParser->errors();
if (!parserErrors.isEmpty()) {
- foreach (QQmlError error, parserErrors)
+ foreach (const QQmlError &error, parserErrors)
compiler->recordError(error);
return false;
}
@@ -2623,10 +2602,8 @@ void QQmlJavaScriptBindingExpressionSimplificationPass::visitMove(QV4::IR::Move
}
if (QV4::IR::Name *n = move->source->asName()) {
- if (n->builtin == QV4::IR::Name::builtin_qml_id_array
- || n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object
- || n->builtin == QV4::IR::Name::builtin_qml_context_object
- || n->builtin == QV4::IR::Name::builtin_qml_scope_object) {
+ if (n->builtin == QV4::IR::Name::builtin_qml_context
+ || n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object) {
// these are free of side-effects
return;
}
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/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 5c2ad45da2..6839c7f609 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -64,12 +64,19 @@ QT_BEGIN_NAMESPACE
F(SetLookup, setLookup) \
F(StoreQObjectProperty, storeQObjectProperty) \
F(LoadQObjectProperty, loadQObjectProperty) \
+ F(StoreScopeObjectProperty, storeScopeObjectProperty) \
+ F(StoreContextObjectProperty, storeContextObjectProperty) \
+ F(LoadScopeObjectProperty, loadScopeObjectProperty) \
+ F(LoadContextObjectProperty, loadContextObjectProperty) \
+ F(LoadIdObject, loadIdObject) \
F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \
F(LoadSingletonQObjectProperty, loadQObjectProperty) \
F(Push, push) \
F(CallValue, callValue) \
F(CallProperty, callProperty) \
F(CallPropertyLookup, callPropertyLookup) \
+ F(CallScopeObjectProperty, callScopeObjectProperty) \
+ F(CallContextObjectProperty, callContextObjectProperty) \
F(CallElement, callElement) \
F(CallActivationProperty, callActivationProperty) \
F(CallGlobalLookup, callGlobalLookup) \
@@ -125,10 +132,8 @@ QT_BEGIN_NAMESPACE
F(Sub, sub) \
F(BinopContext, binopContext) \
F(LoadThis, loadThis) \
- F(LoadQmlIdArray, loadQmlIdArray) \
+ F(LoadQmlContext, loadQmlContext) \
F(LoadQmlImportedScripts, loadQmlImportedScripts) \
- F(LoadQmlContextObject, loadQmlContextObject) \
- F(LoadQmlScopeObject, loadQmlScopeObject) \
F(LoadQmlSingleton, loadQmlSingleton)
#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
@@ -293,6 +298,24 @@ union Instr
Param base;
Param result;
};
+ struct instr_loadScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int propertyIndex;
+ Param base;
+ Param result;
+ };
+ struct instr_loadContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int propertyIndex;
+ Param base;
+ Param result;
+ };
+ struct instr_loadIdObject {
+ MOTH_INSTR_HEADER
+ int index;
+ Param base;
+ Param result;
+ };
struct instr_loadQObjectProperty {
MOTH_INSTR_HEADER
int propertyIndex;
@@ -318,6 +341,18 @@ union Instr
Param base;
Param source;
};
+ struct instr_storeScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ Param base;
+ int propertyIndex;
+ Param source;
+ };
+ struct instr_storeContextObjectProperty {
+ MOTH_INSTR_HEADER
+ Param base;
+ int propertyIndex;
+ Param source;
+ };
struct instr_storeQObjectProperty {
MOTH_INSTR_HEADER
Param base;
@@ -377,6 +412,22 @@ union Instr
Param base;
Param result;
};
+ struct instr_callScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ quint32 argc;
+ quint32 callData;
+ Param base;
+ Param result;
+ };
+ struct instr_callContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ quint32 argc;
+ quint32 callData;
+ Param base;
+ Param result;
+ };
struct instr_callElement {
MOTH_INSTR_HEADER
Param base;
@@ -684,7 +735,7 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
- struct instr_loadQmlIdArray {
+ struct instr_loadQmlContext {
MOTH_INSTR_HEADER
Param result;
};
@@ -692,14 +743,6 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
- struct instr_loadQmlContextObject {
- MOTH_INSTR_HEADER
- Param result;
- };
- struct instr_loadQmlScopeObject {
- MOTH_INSTR_HEADER
- Param result;
- };
struct instr_loadQmlSingleton {
MOTH_INSTR_HEADER
Param result;
@@ -725,15 +768,22 @@ union Instr
instr_storeElementLookup storeElementLookup;
instr_loadProperty loadProperty;
instr_getLookup getLookup;
+ instr_loadScopeObjectProperty loadScopeObjectProperty;
+ instr_loadContextObjectProperty loadContextObjectProperty;
+ instr_loadIdObject loadIdObject;
instr_loadQObjectProperty loadQObjectProperty;
instr_loadAttachedQObjectProperty loadAttachedQObjectProperty;
instr_storeProperty storeProperty;
instr_setLookup setLookup;
+ instr_storeScopeObjectProperty storeScopeObjectProperty;
+ instr_storeContextObjectProperty storeContextObjectProperty;
instr_storeQObjectProperty storeQObjectProperty;
instr_push push;
instr_callValue callValue;
instr_callProperty callProperty;
instr_callPropertyLookup callPropertyLookup;
+ instr_callScopeObjectProperty callScopeObjectProperty;
+ instr_callContextObjectProperty callContextObjectProperty;
instr_callElement callElement;
instr_callActivationProperty callActivationProperty;
instr_callGlobalLookup callGlobalLookup;
@@ -789,10 +839,8 @@ union Instr
instr_sub sub;
instr_binopContext binopContext;
instr_loadThis loadThis;
- instr_loadQmlIdArray loadQmlIdArray;
+ instr_loadQmlContext loadQmlContext;
instr_loadQmlImportedScripts loadQmlImportedScripts;
- instr_loadQmlContextObject loadQmlContextObject;
- instr_loadQmlScopeObject loadQmlScopeObject;
instr_loadQmlSingleton loadQmlSingleton;
static int size(Type type);
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index eb78a0c054..ede1e6938f 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;
}
@@ -461,6 +461,29 @@ void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Ex
addInstruction(call);
}
+void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::CallScopeObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::CallContextObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -565,9 +588,9 @@ void InstructionSelection::loadThisObject(IR::Expr *e)
addInstruction(load);
}
-void InstructionSelection::loadQmlIdArray(IR::Expr *e)
+void InstructionSelection::loadQmlContext(IR::Expr *e)
{
- Instruction::LoadQmlIdArray load;
+ Instruction::LoadQmlContext load;
load.result = getResultParam(e);
addInstruction(load);
}
@@ -579,20 +602,6 @@ void InstructionSelection::loadQmlImportedScripts(IR::Expr *e)
addInstruction(load);
}
-void InstructionSelection::loadQmlContextObject(IR::Expr *e)
-{
- Instruction::LoadQmlContextObject load;
- load.result = getResultParam(e);
- addInstruction(load);
-}
-
-void InstructionSelection::loadQmlScopeObject(IR::Expr *e)
-{
- Instruction::LoadQmlScopeObject load;
- load.result = getResultParam(e);
- addInstruction(load);
-}
-
void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *e)
{
Instruction::LoadQmlSingleton load;
@@ -694,6 +703,25 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
addInstruction(store);
}
+void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::StoreScopeObjectProperty store;
+ store.base = getParam(targetBase);
+ store.propertyIndex = propertyIndex;
+ store.source = getParam(source);
+ addInstruction(store);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::StoreContextObjectProperty store;
+ store.base = getParam(targetBase);
+ store.propertyIndex = propertyIndex;
+ store.source = getParam(source);
+ addInstruction(store);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
Instruction::StoreQObjectProperty store;
@@ -703,6 +731,31 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target
addInstruction(store);
}
+void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::LoadScopeObjectProperty load;
+ load.base = getParam(source);
+ load.propertyIndex = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::LoadContextObjectProperty load;
+ load.base = getParam(source);
+ load.propertyIndex = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else if (kind == IR::Member::MemberOfIdObjectsArray) {
+ Instruction::LoadIdObject load;
+ load.base = getParam(source);
+ load.index = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0) {
@@ -1444,7 +1497,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_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 4ea0f1d07f..ac1eaba740 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -95,6 +95,7 @@ protected:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result);
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
virtual void convertType(IR::Expr *source, IR::Expr *target);
@@ -102,10 +103,8 @@ protected:
virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
virtual void loadThisObject(IR::Expr *e);
- virtual void loadQmlIdArray(IR::Expr *e);
+ virtual void loadQmlContext(IR::Expr *e);
virtual void loadQmlImportedScripts(IR::Expr *e);
- virtual void loadQmlContextObject(IR::Expr *e);
- virtual void loadQmlScopeObject(IR::Expr *e);
virtual void loadQmlSingleton(const QString &name, IR::Expr *e);
virtual void loadConst(IR::Const *sourceConst, IR::Expr *e);
virtual void loadString(const QString &str, IR::Expr *target);
@@ -115,7 +114,9 @@ protected:
virtual void initClosure(IR::Closure *closure, IR::Expr *target);
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target);
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target);
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 54b184b4eb..9d172b1223 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
@@ -91,12 +91,8 @@ void IRDecoder::visitMove(IR::Move *s)
if (IR::Name *n = s->source->asName()) {
if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
loadThisObject(s->target);
- else if (n->builtin == IR::Name::builtin_qml_id_array)
- loadQmlIdArray(s->target);
- else if (n->builtin == IR::Name::builtin_qml_context_object)
- loadQmlContextObject(s->target);
- else if (n->builtin == IR::Name::builtin_qml_scope_object)
- loadQmlScopeObject(s->target);
+ else if (n->builtin == IR::Name::builtin_qml_context)
+ loadQmlContext(s->target);
else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
loadQmlImportedScripts(s->target);
else if (n->qmlSingleton)
@@ -140,8 +136,8 @@ void IRDecoder::visitMove(IR::Move *s)
#else
bool captureRequired = true;
- Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
- const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
+ Q_ASSERT(m->kind != IR::Member::MemberOfEnum && m->kind != IR::Member::MemberOfIdObjectsArray);
+ const int attachedPropertiesId = m->attachedPropertiesId;
const bool isSingletonProperty = m->kind == IR::Member::MemberOfSingletonObject;
if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) {
@@ -153,9 +149,16 @@ void IRDecoder::visitMove(IR::Move *s)
captureRequired = false;
}
}
+ if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
+ getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex, s->target);
+ return;
+ }
getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target);
#endif // V4_BOOTSTRAP
return;
+ } else if (m->kind == IR::Member::MemberOfIdObjectsArray) {
+ getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->idIndex, s->target);
+ return;
} else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
getProperty(m->base, *m->name, s->target);
return;
@@ -174,6 +177,13 @@ void IRDecoder::visitMove(IR::Move *s)
callBuiltin(c, s->target);
return;
} else if (Member *member = c->base->asMember()) {
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, s->target);
+ return;
+ }
+#endif
callProperty(member->base, *member->name, c->args, s->target);
return;
} else if (Subscript *ss = c->base->asSubscript()) {
@@ -192,11 +202,16 @@ void IRDecoder::visitMove(IR::Move *s)
if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
- const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
+ Q_ASSERT(m->kind != IR::Member::MemberOfIdObjectsArray);
+ const int attachedPropertiesId = m->attachedPropertiesId;
if (m->property && attachedPropertiesId == 0) {
#ifdef V4_BOOTSTRAP
Q_UNIMPLEMENTED();
#else
+ if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
+ setQmlContextProperty(s->source, m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex);
+ return;
+ }
setQObjectProperty(s->source, m->base, m->property->coreIndex);
#endif
return;
@@ -238,6 +253,13 @@ void IRDecoder::visitExp(IR::Exp *s)
callValue(c->base, c->args, 0);
} else if (Member *member = c->base->asMember()) {
Q_ASSERT(member->base->asTemp() || member->base->asArgLocal());
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, 0);
+ return;
+ }
+#endif
callProperty(member->base, *member->name, c->args, 0);
} else if (Subscript *s = c->base->asSubscript()) {
callSubscript(s->base, s->index, c->args, 0);
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 1e273df93e..2b8aa7eb33 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -129,6 +129,7 @@ public: // to implement by subclasses:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result) = 0;
virtual void callBuiltinConvertThisToObject() = 0;
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result) = 0;
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result) = 0;
virtual void convertType(IR::Expr *source, IR::Expr *target) = 0;
@@ -136,10 +137,8 @@ public: // to implement by subclasses:
virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
virtual void loadThisObject(IR::Expr *target) = 0;
- virtual void loadQmlIdArray(IR::Expr *target) = 0;
+ virtual void loadQmlContext(IR::Expr *target) = 0;
virtual void loadQmlImportedScripts(IR::Expr *target) = 0;
- virtual void loadQmlContextObject(IR::Expr *target) = 0;
- virtual void loadQmlScopeObject(IR::Expr *target) = 0;
virtual void loadQmlSingleton(const QString &name, IR::Expr *target) = 0;
virtual void loadConst(IR::Const *sourceConst, IR::Expr *target) = 0;
virtual void loadString(const QString &str, IR::Expr *target) = 0;
@@ -149,7 +148,9 @@ public: // to implement by subclasses:
virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0;
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0;
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0;
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) = 0;
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0;
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) = 0;
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0;
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target) = 0;
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex) = 0;
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 5c9cc98ade..98b53c6b3b 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -341,14 +341,10 @@ const char *builtin_to_string(Name::Builtin b)
return "builtin_setup_argument_object";
case IR::Name::builtin_convert_this_to_object:
return "builtin_convert_this_to_object";
- case IR::Name::builtin_qml_id_array:
- return "builtin_qml_id_array";
+ case IR::Name::builtin_qml_context:
+ return "builtin_qml_context";
case IR::Name::builtin_qml_imported_scripts_object:
return "builtin_qml_imported_scripts_object";
- case IR::Name::builtin_qml_scope_object:
- return "builtin_qml_scope_object";
- case IR::Name::builtin_qml_context_object:
- return "builtin_qml_context_object";
}
return "builtin_(###FIXME)";
};
@@ -935,7 +931,7 @@ void CloneExpr::visitSubscript(Subscript *e)
void CloneExpr::visitMember(Member *e)
{
Expr *clonedBase = clone(e->base);
- cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->attachedPropertiesIdOrEnumValue);
+ cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->idIndex);
}
IRPrinter::IRPrinter(QTextStream *out)
@@ -1239,9 +1235,9 @@ void IRPrinter::visitSubscript(Subscript *e)
void IRPrinter::visitMember(Member *e)
{
- if (e->kind != Member::MemberOfEnum
- && e->attachedPropertiesIdOrEnumValue != 0 && !e->base->asTemp())
- *out << "[[attached property from " << e->attachedPropertiesIdOrEnumValue << "]]";
+ if (e->kind != Member::MemberOfEnum && e->kind != Member::MemberOfIdObjectsArray
+ && e->attachedPropertiesId != 0 && !e->base->asTemp())
+ *out << "[[attached property from " << e->attachedPropertiesId << "]]";
else
e->base->accept(this);
*out << '.' << *e->name;
@@ -1250,6 +1246,8 @@ void IRPrinter::visitMember(Member *e)
*out << " (meta-property " << e->property->coreIndex
<< " <" << QMetaType::typeName(e->property->propType)
<< ">)";
+ else if (e->kind == Member::MemberOfIdObjectsArray)
+ *out << "(id object " << e->idIndex << ")";
#endif
}
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 8daad97e8b..568ded5337 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -337,10 +337,8 @@ struct Name: Expr {
builtin_define_object_literal,
builtin_setup_argument_object,
builtin_convert_this_to_object,
- builtin_qml_id_array,
- builtin_qml_imported_scripts_object,
- builtin_qml_context_object,
- builtin_qml_scope_object
+ builtin_qml_context,
+ builtin_qml_imported_scripts_object
};
const QString *id;
@@ -558,13 +556,18 @@ struct Member: Expr {
MemberOfEnum,
MemberOfQmlScopeObject,
MemberOfQmlContextObject,
- MemberOfSingletonObject
+ MemberOfIdObjectsArray,
+ MemberOfSingletonObject,
};
Expr *base;
const QString *name;
QQmlPropertyData *property;
- int attachedPropertiesIdOrEnumValue; // depending on kind
+ union { // depending on kind
+ int attachedPropertiesId;
+ int enumValue;
+ int idIndex;
+ };
uchar freeOfSideEffects : 1;
// This is set for example for for QObject properties. All sorts of extra behavior
@@ -577,20 +580,20 @@ struct Member: Expr {
void setEnumValue(int value) {
kind = MemberOfEnum;
- attachedPropertiesIdOrEnumValue = value;
+ enumValue = value;
}
void setAttachedPropertiesId(int id) {
- Q_ASSERT(kind != MemberOfEnum);
- attachedPropertiesIdOrEnumValue = id;
+ Q_ASSERT(kind != MemberOfEnum && kind != MemberOfIdObjectsArray);
+ attachedPropertiesId = id;
}
- void init(Expr *base, const QString *name, QQmlPropertyData *property = 0, uchar kind = UnspecifiedMember, int attachedPropertiesIdOrEnumValue = 0)
+ void init(Expr *base, const QString *name, QQmlPropertyData *property = 0, uchar kind = UnspecifiedMember, int index = 0)
{
this->base = base;
this->name = name;
this->property = property;
- this->attachedPropertiesIdOrEnumValue = attachedPropertiesIdOrEnumValue;
+ this->idIndex = index;
this->freeOfSideEffects = false;
this->inhibitTypeConversionOnWrite = property != 0;
this->kind = kind;
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index c0669d3e47..c150666a11 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -3912,7 +3912,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
QString name;
if (f->name) name = *f->name;
- else name = QString::fromLatin1("%1").arg((unsigned long long)f);
+ else name = QStringLiteral("%1").arg((unsigned long long)f);
qout << "digraph \"" << name << "\" { ordering=out;\n";
foreach (LoopDetection::LoopInfo *l, loops) {
@@ -4020,14 +4020,14 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
if (Member *member = m->source->asMember()) {
if (member->kind == Member::MemberOfEnum) {
Const *c = function->New<Const>();
- const int enumValue = member->attachedPropertiesIdOrEnumValue;
+ const int enumValue = member->enumValue;
c->init(SInt32Type, enumValue);
replaceUses(targetTemp, c, W);
defUses.removeDef(*targetTemp);
W.remove(s);
defUses.removeUse(s, *member->base->asTemp());
continue;
- } else if (member->attachedPropertiesIdOrEnumValue != 0 && member->property && member->base->asTemp()) {
+ } else if (member->kind != IR::Member::MemberOfIdObjectsArray && member->attachedPropertiesId != 0 && member->property && member->base->asTemp()) {
// Attached properties have no dependency on their base. Isel doesn't
// need it and we can eliminate the temp used to initialize it.
defUses.removeUse(s, *member->base->asTemp());
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index 77a3ba6490..30a44eedd1 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -1,36 +1,23 @@
+contains(QT_CONFIG, no-qml-debug):DEFINES += QT_NO_QML_DEBUGGER
+
SOURCES += \
+ $$PWD/qqmldebug.cpp \
+ $$PWD/qqmldebugconnector.cpp \
$$PWD/qqmldebugservice.cpp \
- $$PWD/qqmlprofilerservice.cpp \
- $$PWD/qqmldebugserver.cpp \
- $$PWD/qqmlinspectorservice.cpp \
- $$PWD/qqmlenginedebugservice.cpp \
- $$PWD/qdebugmessageservice.cpp \
- $$PWD/qv4debugservice.cpp \
- $$PWD/qqmlconfigurabledebugservice.cpp \
- $$PWD/qqmlenginecontrolservice.cpp \
+ $$PWD/qqmldebugserviceinterfaces.cpp \
$$PWD/qqmlabstractprofileradapter.cpp \
- $$PWD/qv4profileradapter.cpp \
$$PWD/qqmlprofiler.cpp
HEADERS += \
+ $$PWD/qqmldebugconnector_p.h \
+ $$PWD/qqmldebugpluginmanager_p.h \
$$PWD/qqmldebugservice_p.h \
- $$PWD/qqmldebugservice_p_p.h \
- $$PWD/qqmlprofilerservice_p.h \
- $$PWD/qqmldebugserver_p.h \
- $$PWD/qqmldebugserverconnection_p.h \
+ $$PWD/qqmldebugservicefactory_p.h \
+ $$PWD/qqmldebugserviceinterfaces_p.h \
$$PWD/qqmldebugstatesdelegate_p.h \
- $$PWD/qqmlinspectorservice_p.h \
- $$PWD/qqmlinspectorinterface_p.h \
- $$PWD/qqmlenginedebugservice_p.h \
$$PWD/qqmldebug.h \
- $$PWD/qdebugmessageservice_p.h \
- $$PWD/qv4debugservice_p.h \
- $$PWD/qqmlconfigurabledebugservice_p.h \
- $$PWD/qqmlconfigurabledebugservice_p_p.h \
- $$PWD/qqmlenginecontrolservice_p.h \
$$PWD/qqmlprofilerdefinitions_p.h \
$$PWD/qqmlabstractprofileradapter_p.h \
- $$PWD/qv4profileradapter_p.h \
$$PWD/qqmlprofiler_p.h
INCLUDEPATH += $$PWD
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice.cpp b/src/qml/debugger/qqmlconfigurabledebugservice.cpp
deleted file mode 100644
index e3693e00a4..0000000000
--- a/src/qml/debugger/qqmlconfigurabledebugservice.cpp
+++ /dev/null
@@ -1,88 +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$
-**
-****************************************************************************/
-
-#include "qqmlconfigurabledebugservice_p.h"
-#include "qqmlconfigurabledebugservice_p_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QQmlConfigurableDebugService::QQmlConfigurableDebugService(const QString &name, float version,
- QObject *parent) :
- QQmlDebugService((*new QQmlConfigurableDebugServicePrivate), name, version, parent) { init(); }
-
-QQmlConfigurableDebugService::QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd,
- const QString &name, float version,
- QObject *parent) :
- QQmlDebugService(dd, name, version, parent) { init(); }
-
-QMutex *QQmlConfigurableDebugService::configMutex()
-{
- Q_D(QQmlConfigurableDebugService);
- return &d->configMutex;
-}
-
-void QQmlConfigurableDebugService::init()
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- // If we're not enabled or not blocking, don't wait for configuration
- d->waitingForConfiguration = (registerService() == Enabled && blockingMode());
-}
-
-void QQmlConfigurableDebugService::stopWaiting()
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- d->waitingForConfiguration = false;
- foreach (QQmlEngine *engine, d->waitingEngines)
- emit attachedToEngine(engine);
- d->waitingEngines.clear();
-}
-
-void QQmlConfigurableDebugService::stateChanged(QQmlDebugService::State newState)
-{
- if (newState != Enabled)
- stopWaiting();
-}
-
-void QQmlConfigurableDebugService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- if (d->waitingForConfiguration)
- d->waitingEngines.append(engine);
- else
- emit attachedToEngine(engine);
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
new file mode 100644
index 0000000000..83718921f1
--- /dev/null
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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 "qqmldebug.h"
+#include "qqmldebugconnector_p.h"
+
+#include <private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ if (!QQmlEnginePrivate::qml_debugging_enabled
+ && printWarning) {
+ qDebug("QML debugging is enabled. Only use this in a safe environment.");
+ }
+ QQmlEnginePrivate::qml_debugging_enabled = true;
+#else
+ Q_UNUSED(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
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QQmlDebugConnector *connector = QQmlDebugConnector::instance();
+ if (connector) {
+ QVariantHash configuration;
+ configuration[QLatin1String("portFrom")] = configuration[QLatin1String("portTo")] = port;
+ configuration[QLatin1String("block")] = (mode == WaitForClient);
+ configuration[QLatin1String("hostAddress")] = hostName;
+ return connector->open(configuration);
+ }
+#else
+ Q_UNUSED(port);
+ Q_UNUSED(block);
+ Q_UNUSED(hostName);
+#endif
+ return false;
+}
+
+/*!
+ * 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 mode is \c WaitForClient. If \a mode is not
+ * specified it will not 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, StartMode mode)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QQmlDebugConnector *connector = QQmlDebugConnector::instance();
+ if (connector) {
+ QVariantHash configuration;
+ configuration[QLatin1String("fileName")] = socketFileName;
+ configuration[QLatin1String("block")] = (mode == WaitForClient);
+ return connector->open(configuration);
+ }
+#else
+ Q_UNUSED(fileName);
+ Q_UNUSED(block);
+#endif
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 559c492dfd..5d65982a49 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -50,6 +50,8 @@ 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,
+ StartMode mode = DoNotWaitForClient);
};
// Execute code in constructor before first QQmlEngine is instantiated
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
new file mode 100644
index 0000000000..8de734fa68
--- /dev/null
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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 "qqmldebugpluginmanager_p.h"
+#include "qqmldebugconnector_p.h"
+#include "qqmldebugservicefactory_p.h"
+#include <QtCore/QPluginLoader>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QJsonArray>
+
+#include <private/qcoreapplication_p.h>
+#include <private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// We could add more plugins here, and distinguish by arguments to instance()
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugConnector)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebugServerFactory)
+
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugService)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlInspectorServiceFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlProfilerServiceFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebuggerServiceFactory)
+
+struct QQmlDebugConnectorParams {
+ QString pluginKey;
+ QStringList services;
+ QString arguments;
+ QQmlDebugConnector *instance;
+
+ QQmlDebugConnectorParams() : instance(0)
+ {
+ if (qApp) {
+ QCoreApplicationPrivate *appD =
+ static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
+ if (appD)
+ arguments = appD->qmljsDebugArgumentsString();
+ }
+ }
+};
+
+Q_GLOBAL_STATIC(QQmlDebugConnectorParams, qmlDebugConnectorParams)
+
+void QQmlDebugConnector::setPluginKey(const QString &key)
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params) {
+ if (params->instance)
+ qWarning() << "QML debugger: Cannot set plugin key after loading the plugin.";
+ else
+ params->pluginKey = key;
+ }
+}
+
+void QQmlDebugConnector::setServices(const QStringList &services)
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params)
+ params->services = services;
+}
+
+QString QQmlDebugConnector::commandLineArguments()
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (!params)
+ return QString();
+ return params->arguments;
+}
+
+QQmlDebugConnector *QQmlDebugConnector::instance()
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (!params)
+ return 0;
+
+ if (!QQmlEnginePrivate::qml_debugging_enabled) {
+ if (!params->arguments.isEmpty()) {
+ qWarning() << QString::fromLatin1(
+ "QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging has not "
+ "been enabled.").arg(params->arguments);
+ params->arguments.clear();
+ }
+ return 0;
+ }
+
+ if (!params->instance) {
+ if (!params->pluginKey.isEmpty()) {
+ if (params->pluginKey != QLatin1String("QQmlDebugServer"))
+ return 0; // We cannot load anything else, yet
+ } else if (params->arguments.isEmpty()) {
+ return 0; // no explicit class name given and no command line arguments
+ }
+ params->instance = loadQQmlDebugConnector(QLatin1String("QQmlDebugServer"));
+ if (params->instance) {
+ foreach (const QJsonObject &object, metaDataForQQmlDebugService()) {
+ foreach (const QJsonValue &key, object.value(QLatin1String("MetaData")).toObject()
+ .value(QLatin1String("Keys")).toArray()) {
+ QString keyString = key.toString();
+ if (params->services.isEmpty() || params->services.contains(keyString))
+ loadQQmlDebugService(keyString);
+ }
+ }
+ }
+ }
+
+ return params->instance;
+}
+
+QQmlDebugConnectorFactory::~QQmlDebugConnectorFactory()
+{
+ // This is triggered when the plugin is unloaded.
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params && params->instance) {
+ delete params->instance;
+ params->instance = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlinspectorservice_p.h b/src/qml/debugger/qqmldebugconnector_p.h
index f49c36aacb..f5f5a87b56 100644
--- a/src/qml/debugger/qqmlinspectorservice_p.h
+++ b/src/qml/debugger/qqmldebugconnector_p.h
@@ -31,8 +31,13 @@
**
****************************************************************************/
-#ifndef QQMLINSPECTORSERVICE_H
-#define QQMLINSPECTORSERVICE_H
+#ifndef QQMLDEBUGCONNECTOR_H
+#define QQMLDEBUGCONNECTOR_H
+
+#include <QtQml/qtqmlglobal.h>
+#include <QtCore/QVariantList>
+
+#include <private/qqmldebugservice_p.h>
//
// W A R N I N G
@@ -45,45 +50,49 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
-
-#include <QtQml/qtqmlglobal.h>
-#include <QtCore/QList>
-
QT_BEGIN_NAMESPACE
-
-class QQmlInspectorInterface;
-
-class Q_QML_PRIVATE_EXPORT QQmlInspectorService : public QQmlDebugService
+class QQmlDebugService;
+class Q_QML_PRIVATE_EXPORT QQmlDebugConnector : public QObject
{
Q_OBJECT
-
public:
- QQmlInspectorService();
- static QQmlInspectorService *instance();
+ static void setPluginKey(const QString &key);
+ static void setServices(const QStringList &services);
+ static QQmlDebugConnector *instance();
- void addView(QObject *);
- void removeView(QObject *);
+ virtual bool blockingMode() const = 0;
- void sendMessage(const QByteArray &message);
+ virtual QQmlDebugService *service(const QString &name) const = 0;
-protected:
- virtual void stateChanged(State state);
- virtual void messageReceived(const QByteArray &);
+ virtual void addEngine(QQmlEngine *engine) = 0;
+ virtual void removeEngine(QQmlEngine *engine) = 0;
+
+ virtual bool addService(const QString &name, QQmlDebugService *service) = 0;
+ virtual bool removeService(const QString &name) = 0;
-private Q_SLOTS:
- void processMessage(const QByteArray &message);
- void updateState();
+ virtual bool open(const QVariantHash &configuration = QVariantHash()) = 0;
-private:
- void loadInspectorPlugins();
+ template<class Service>
+ static Service *service()
+ {
+ QQmlDebugConnector *inst = instance();
+ return inst ? static_cast<Service *>(inst->service(Service::s_key)) : 0;
+ }
+
+protected:
+ static QString commandLineArguments();
+};
- QList<QObject*> m_views;
- QQmlInspectorInterface *m_currentInspectorPlugin;
- QList<QQmlInspectorInterface*> m_inspectorPlugins;
+class Q_QML_PRIVATE_EXPORT QQmlDebugConnectorFactory : public QObject {
+ Q_OBJECT
+public:
+ virtual QQmlDebugConnector *create(const QString &key) = 0;
+ ~QQmlDebugConnectorFactory();
};
+#define QQmlDebugConnectorFactory_iid "org.qt-project.Qt.QQmlDebugConnectorFactory"
+
QT_END_NAMESPACE
-#endif // QQMLINSPECTORSERVICE_H
+#endif // QQMLDEBUGCONNECTOR_H
diff --git a/src/qml/debugger/qqmldebugpluginmanager_p.h b/src/qml/debugger/qqmldebugpluginmanager_p.h
new file mode 100644
index 0000000000..cef463b8b3
--- /dev/null
+++ b/src/qml/debugger/qqmldebugpluginmanager_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGPLUGINMANAGER_P_H
+#define QQMLDEBUGPLUGINMANAGER_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 <QDebug>
+#include <private/qtqmlglobal_p.h>
+#include <private/qfactoryloader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_NO_QML_DEBUGGER)
+
+#define Q_QML_DEBUG_PLUGIN_LOADER(interfaceName)\
+ interfaceName *load##interfaceName(const QString &key)\
+ {\
+ qWarning() << "Qml Debugger: QtQml is not configured for debugging. Ignoring request for"\
+ << "debug plugin" << key;\
+ return 0;\
+ }\
+ QList<QJsonObject> metaDataFor##interfaceName()\
+ {\
+ return QList<QJsonObject();\
+ }
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)
+
+#else // QT_NO_QML_DEBUGGER
+
+#ifdef QT_STATIC
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)\
+ Q_IMPORT_PLUGIN(className)
+#else
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)
+#endif // QT_STATIC
+
+#define Q_QML_DEBUG_PLUGIN_LOADER(interfaceName)\
+ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, interfaceName##Loader,\
+ (interfaceName##Factory_iid, QLatin1String("/qmltooling")))\
+ interfaceName *load##interfaceName(const QString &key)\
+ {\
+ return qLoadPlugin<interfaceName, interfaceName##Factory>(interfaceName##Loader(), key);\
+ }\
+ QList<QJsonObject> metaDataFor##interfaceName()\
+ {\
+ return interfaceName##Loader()->metaData();\
+ }
+
+#endif // QT_NO_QML_DEBUGGER
+
+QT_END_NAMESPACE
+#endif // QQMLDEBUGPLUGINMANAGER_P_H
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
deleted file mode 100644
index b0302181ee..0000000000
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ /dev/null
@@ -1,787 +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$
-**
-****************************************************************************/
-
-#include "qqmldebugserver_p.h"
-#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
-#include "qqmlenginedebugservice_p.h"
-#include "qv4debugservice_p.h"
-#include "qdebugmessageservice_p.h"
-#include "qqmlprofilerservice_p.h"
-
-#include <private/qqmlengine_p.h>
-#include <private/qqmlglobal_p.h>
-
-#include <QtCore/QAtomicInt>
-#include <QtCore/QDir>
-#include <QtCore/QPluginLoader>
-#include <QtCore/QStringList>
-#include <QtCore/qwaitcondition.h>
-
-#include <private/qobject_p.h>
-#include <private/qcoreapplication_p.h>
-
-#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
-#include "../../plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h"
-#endif
-
-QT_BEGIN_NAMESPACE
-
-// We can't friend the Q_GLOBAL_STATIC to have the constructor available so we need a little
-// workaround here. Using this wrapper we can also make QQmlEnginePrivate's cleanup() available to
-// qAddPostRoutine(). We can't do the cleanup in the destructor because we need a QApplication to
-// be available when stopping the plugins.
-struct QQmlDebugServerInstanceWrapper {
- QQmlDebugServer m_instance;
- void cleanup();
-};
-
-Q_GLOBAL_STATIC(QQmlDebugServerInstanceWrapper, debugServerInstance)
-
-/*
- QQmlDebug Protocol (Version 1):
-
- handshake:
- 1. Client sends
- "QDeclarativeDebugServer" 0 version pluginNames [QDataStream version]
- version: an int representing the highest protocol version the client knows
- pluginNames: plugins available on client side
- 2. Server sends
- "QDeclarativeDebugClient" 0 version pluginNames pluginVersions [QDataStream version]
- version: an int representing the highest protocol version the client & server know
- pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
- client plugin advertisement
- 1. Client sends
- "QDeclarativeDebugServer" 1 pluginNames
- server plugin advertisement
- 1. Server sends
- "QDeclarativeDebugClient" 1 pluginNames pluginVersions
- plugin communication:
- Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
- */
-
-const int protocolVersion = 1;
-int QQmlDebugServer::s_dataStreamVersion = QDataStream::Qt_4_7;
-
-// print detailed information about loading of plugins
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
-
-class QQmlDebugServerThread;
-
-class QQmlDebugServerPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlDebugServer)
-public:
- QQmlDebugServerPrivate();
-
- bool start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName);
- void advertisePlugins();
- void cleanup();
- QQmlDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
-
- QQmlDebugServerConnection *connection;
- QHash<QString, QQmlDebugService *> plugins;
- mutable QReadWriteLock pluginsLock;
- QStringList clientPlugins;
- bool gotHello;
- bool blockingMode;
-
- class EngineCondition {
- public:
- EngineCondition() : numServices(0), condition(new QWaitCondition) {}
-
- bool waitForServices(QReadWriteLock *locked, int numEngines);
-
- void wake();
- private:
- int numServices;
-
- // shared pointer to allow for QHash-inflicted copying.
- QSharedPointer<QWaitCondition> condition;
- };
-
- QHash<QQmlEngine *, EngineCondition> engineConditions;
-
- QMutex helloMutex;
- QWaitCondition helloCondition;
- QQmlDebugServerThread *thread;
- QPluginLoader loader;
- QAtomicInt changeServiceStateCalls;
-
-private:
- // private slots
- void _q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State newState);
- void _q_sendMessages(const QList<QByteArray> &messages);
- void _q_removeThread();
-};
-
-void QQmlDebugServerInstanceWrapper::cleanup()
-{ m_instance.d_func()->cleanup(); }
-
-class QQmlDebugServerThread : public QThread
-{
-public:
- void setPluginName(const QString &pluginName) {
- m_pluginName = pluginName;
- }
-
- void setPortRange(int portFrom, int portTo, bool block, const QString &hostAddress) {
- m_portFrom = portFrom;
- m_portTo = portTo;
- m_block = block;
- m_hostAddress = hostAddress;
- }
-
- void run();
-
-private:
- QString m_pluginName;
- int m_portFrom;
- int m_portTo;
- bool m_block;
- QString m_hostAddress;
-};
-
-QQmlDebugServerPrivate::QQmlDebugServerPrivate() :
- connection(0),
- pluginsLock(QReadWriteLock::Recursive),
- gotHello(false),
- blockingMode(false),
- thread(0)
-{
- // used in _q_sendMessages
- qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
- // used in _q_changeServiceState
- qRegisterMetaType<QQmlDebugService::State>("QQmlDebugService::State");
-}
-
-void QQmlDebugServerPrivate::advertisePlugins()
-{
- Q_Q(QQmlDebugServer);
-
- if (!gotHello)
- return;
-
- QByteArray message;
- {
- QQmlDebugStream out(&message, QIODevice::WriteOnly);
- QStringList pluginNames;
- QList<float> pluginVersions;
- foreach (QQmlDebugService *service, plugins.values()) {
- pluginNames << service->name();
- pluginVersions << service->version();
- }
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 1 << pluginNames << pluginVersions;
- }
-
- QMetaObject::invokeMethod(q, "_q_sendMessages", Qt::QueuedConnection, Q_ARG(QList<QByteArray>, QList<QByteArray>() << message));
-}
-
-void QQmlDebugServerPrivate::cleanup()
-{
- Q_Q(QQmlDebugServer);
- {
- QReadLocker lock(&pluginsLock);
- foreach (QQmlDebugService *service, plugins.values()) {
- changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(q, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, QQmlDebugService::NotConnected));
- }
- }
-
- // Wait for changeServiceState calls to finish
- // (while running an event loop because some services
- // might again use slots to execute stuff in the GUI thread)
- QEventLoop loop;
- while (!changeServiceStateCalls.testAndSetOrdered(0, 0))
- loop.processEvents();
-
- // Stop the thread while the application is still there. Copy here as the thread will set itself
- // to 0 when it stops. It will also do deleteLater, but as long as we don't allow the GUI
- // thread's event loop to run we're safe from that.
- QThread *threadCopy = thread;
- if (threadCopy) {
- threadCopy->exit();
- threadCopy->wait();
- }
-}
-
-QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
- const QString &pluginName)
-{
-#ifndef QT_NO_LIBRARY
- QStringList pluginCandidates;
- const QStringList paths = QCoreApplication::libraryPaths();
- foreach (const QString &libPath, paths) {
- const QDir dir(libPath + QLatin1String("/qmltooling"));
- if (dir.exists()) {
- QStringList plugins(dir.entryList(QDir::Files));
- foreach (const QString &pluginPath, plugins) {
- if (QFileInfo(pluginPath).fileName().contains(pluginName))
- pluginCandidates << dir.absoluteFilePath(pluginPath);
- }
- }
- }
-
- QQmlDebugServerConnection *loadedConnection = 0;
- foreach (const QString &pluginPath, pluginCandidates) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Trying to load plugin " << pluginPath << "...";
-
- loader.setFileName(pluginPath);
- if (!loader.load()) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Error while loading: " << loader.errorString();
- continue;
- }
- if (QObject *instance = loader.instance())
- loadedConnection = qobject_cast<QQmlDebugServerConnection*>(instance);
-
- if (loadedConnection) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Plugin successfully loaded.";
-
- return loadedConnection;
- }
-
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Plugin does not implement interface QQmlDebugServerConnection.";
-
- loader.unload();
- }
-#endif
- return 0;
-}
-
-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)
- QQmlDebugServerConnection *connection
- = new QTcpServerConnection;
-#else
- QQmlDebugServerConnection *connection
- = server->d_func()->loadConnectionPlugin(m_pluginName);
-#endif
- if (connection) {
- connection->setServer(server);
- if (!connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress)) {
- delete connection;
- return;
- }
- server->d_func()->connection = connection;
- if (m_block)
- connection->waitForConnection();
- } else {
- qWarning() << "QML Debugger: Couldn't load plugin" << m_pluginName;
- return;
- }
-
- exec();
-
- // make sure events still waiting are processed
- QEventLoop eventLoop;
- eventLoop.processEvents(QEventLoop::AllEvents);
-}
-
-bool QQmlDebugServer::hasDebuggingClient() const
-{
- Q_D(const QQmlDebugServer);
- return d->connection
- && d->connection->isConnected()
- && d->gotHello;
-}
-
-bool QQmlDebugServer::hasThread() const
-{
- Q_D(const QQmlDebugServer);
- return d->thread != 0;
-}
-
-bool QQmlDebugServer::hasConnection() const
-{
- Q_D(const QQmlDebugServer);
- return d->connection != 0;
-}
-
-bool QQmlDebugServer::blockingMode() const
-{
- Q_D(const QQmlDebugServer);
- return d->blockingMode;
-}
-
-QQmlDebugServer *QQmlDebugServer::instance()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (wrapper && wrapper->m_instance.d_func()->thread) {
- QQmlDebugServer *ret = &(wrapper->m_instance);
- QQmlDebugServerPrivate *d = ret->d_func();
- QMutexLocker locker(&d->helloMutex);
- if (d->blockingMode && !d->gotHello)
- d->helloCondition.wait(&d->helloMutex);
- return ret;
- } else {
- return 0;
- }
-}
-
-static void cleanupOnShutdown()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (wrapper)
- wrapper->cleanup();
-}
-
-bool QQmlDebugServerPrivate::start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName)
-{
- if (!QQmlEnginePrivate::qml_debugging_enabled)
- return false;
- if (thread)
- return false;
- static bool postRoutineAdded = false;
- if (!postRoutineAdded) {
- qAddPostRoutine(cleanupOnShutdown);
- postRoutineAdded = true;
- }
- Q_Q(QQmlDebugServer);
- thread = new QQmlDebugServerThread;
- q->moveToThread(thread);
-
- // Remove the thread immmediately when it finishes, so that we don't have to wait for the event
- // loop to signal that.
- QObject::connect(thread, SIGNAL(finished()), q, SLOT(_q_removeThread()), Qt::DirectConnection);
-
- thread->setObjectName(QStringLiteral("QQmlDebugServerThread"));
- thread->setPluginName(pluginName);
- thread->setPortRange(portFrom, portTo == -1 ? portFrom : portTo, block, hostAddress);
- blockingMode = block;
- thread->start();
- return true;
-}
-
-QQmlDebugServer::QQmlDebugServer()
- : QObject(*(new QQmlDebugServerPrivate))
-{
- if (qApp == 0)
- return;
- QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
-#ifndef QT_NO_QML_DEBUGGER
- // ### remove port definition when protocol is changed
- int portFrom = 0;
- int portTo = 0;
- bool block = false;
- bool ok = false;
- QString hostAddress;
-
- // format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- if (!QQmlEnginePrivate::qml_debugging_enabled) {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Debugging has not been enabled.")).arg(
- appD->qmljsDebugArgumentsString());
- return;
- }
-
- QString pluginName;
- QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString()
- .split(QLatin1Char(','));
- QStringList::const_iterator argsItEnd = lstjsDebugArguments.end();
- QStringList::const_iterator argsIt = lstjsDebugArguments.begin();
- for (; argsIt != argsItEnd; ++argsIt) {
- const QString strArgument = *argsIt;
- if (strArgument.startsWith(QLatin1String("port:"))) {
- pluginName = QLatin1String("qmldbg_tcp");
- portFrom = strArgument.mid(5).toInt(&ok);
- portTo = portFrom;
- QStringList::const_iterator argsNext = argsIt + 1;
- if (argsNext == argsItEnd)
- break;
- const QString nextArgument = *argsNext;
- if (ok && nextArgument.contains(QRegExp(QStringLiteral("^\\s*\\d+\\s*$")))) {
- portTo = nextArgument.toInt(&ok);
- ++argsIt;
- }
- } else if (strArgument.startsWith(QLatin1String("host:"))) {
- hostAddress = strArgument.mid(5);
- } else if (strArgument == QLatin1String("block")) {
- block = true;
- } else {
- qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
- "detected. Ignoring the same.")
- .arg(strArgument);
- }
- }
-
- if (ok) {
- Q_D(QQmlDebugServer);
- d->start(portFrom, portTo, block, hostAddress, pluginName);
- } else {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
- "<ip address>][,block]")).arg(appD->qmljsDebugArgumentsString());
- }
- }
-#else
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "QtQml is not configured for debugging.")).arg(
- appD->qmljsDebugArgumentsString());
- }
-#endif
-}
-
-void QQmlDebugServer::receiveMessage(const QByteArray &message)
-{
- typedef QHash<QString, QQmlDebugService*>::const_iterator DebugServiceConstIt;
-
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == thread());
-
- Q_D(QQmlDebugServer);
-
- QQmlDebugStream in(message);
-
- QString name;
-
- in >> name;
- if (name == QLatin1String("QDeclarativeDebugServer")) {
- int op = -1;
- in >> op;
- if (op == 0) {
- QWriteLocker lock(&d->pluginsLock);
- int version;
- in >> version >> d->clientPlugins;
-
- //Get the supported QDataStream version
- if (!in.atEnd()) {
- in >> s_dataStreamVersion;
- if (s_dataStreamVersion > QDataStream().version())
- s_dataStreamVersion = QDataStream().version();
- }
-
- // Send the hello answer immediately, since it needs to arrive before
- // the plugins below start sending messages.
-
- QByteArray helloAnswer;
- QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
- QStringList pluginNames;
- QList<float> pluginVersions;
- foreach (QQmlDebugService *service, d->plugins.values()) {
- pluginNames << service->name();
- pluginVersions << service->version();
- }
-
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
- << pluginNames << pluginVersions << s_dataStreamVersion;
-
- d->connection->send(QList<QByteArray>() << helloAnswer);
-
- QMutexLocker helloLock(&d->helloMutex);
- d->gotHello = true;
-
- for (DebugServiceConstIt iter = d->plugins.constBegin(), cend = d->plugins.constEnd(); iter != cend; ++iter) {
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(iter.key()))
- newState = QQmlDebugService::Enabled;
- d->changeServiceStateCalls.ref();
- d->_q_changeServiceState(iter.value()->name(), newState);
- }
-
- d->helloCondition.wakeAll();
-
- } else if (op == 1) {
- QWriteLocker lock(&d->pluginsLock);
-
- // Service Discovery
- QStringList oldClientPlugins = d->clientPlugins;
- in >> d->clientPlugins;
-
- for (DebugServiceConstIt iter = d->plugins.constBegin(), cend = d->plugins.constEnd(); iter != cend; ++iter) {
- const QString pluginName = iter.key();
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(pluginName))
- newState = QQmlDebugService::Enabled;
-
- if (oldClientPlugins.contains(pluginName)
- != d->clientPlugins.contains(pluginName)) {
- d->changeServiceStateCalls.ref();
- d->_q_changeServiceState(iter.value()->name(), newState);
- }
- }
-
- } else {
- qWarning("QML Debugger: Invalid control message %d.", op);
- d->connection->disconnect();
- return;
- }
-
- } else {
- if (d->gotHello) {
- QByteArray message;
- in >> message;
-
- QReadLocker lock(&d->pluginsLock);
- QHash<QString, QQmlDebugService *>::Iterator iter = d->plugins.find(name);
- if (iter == d->plugins.end()) {
- qWarning() << "QML Debugger: Message received for missing plugin" << name << '.';
- } else {
- (*iter)->messageReceived(message);
- }
- } else {
- qWarning("QML Debugger: Invalid hello message.");
- }
-
- }
-}
-
-void QQmlDebugServerPrivate::_q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State newState)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == q_func()->thread());
-
- QQmlDebugService *service = 0;
- {
- // Write lock here, because this can be called from receiveMessage which already has a write
- // lock. We cannot downgrade it. We also don't want to give up the write lock and later get
- // a read lock as that technique has great potential for deadlocks.
- QWriteLocker lock(&pluginsLock);
- service = plugins.value(serviceName);
- }
-
- if (service && (service->d_func()->state != newState)) {
- service->stateAboutToBeChanged(newState);
- service->d_func()->state = newState;
- service->stateChanged(newState);
- }
-
- changeServiceStateCalls.deref();
-}
-
-void QQmlDebugServerPrivate::_q_sendMessages(const QList<QByteArray> &messages)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == q_func()->thread());
-
- if (connection)
- connection->send(messages);
-}
-
-void QQmlDebugServerPrivate::_q_removeThread()
-{
- Q_ASSERT(thread->isFinished());
- Q_ASSERT(QThread::currentThread() == thread);
-
- QThread *parentThread = thread->thread();
-
- // We cannot delete it right away as it will access its data after the finished() signal.
- thread->deleteLater();
- thread = 0;
-
- delete connection;
- connection = 0;
-
- // Move it back to the parent thread so that we can potentially restart it on a new thread.
- q_func()->moveToThread(parentThread);
-}
-
-QList<QQmlDebugService*> QQmlDebugServer::services() const
-{
- Q_D(const QQmlDebugServer);
- QReadLocker lock(&d->pluginsLock);
- return d->plugins.values();
-}
-
-QStringList QQmlDebugServer::serviceNames() const
-{
- Q_D(const QQmlDebugServer);
- QReadLocker lock(&d->pluginsLock);
- return d->plugins.keys();
-}
-
-void QQmlDebugServer::addEngine(QQmlEngine *engine)
-{
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAboutToBeAdded(engine);
-
- d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAdded(engine);
-}
-
-void QQmlDebugServer::removeEngine(QQmlEngine *engine)
-{
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAboutToBeRemoved(engine);
-
- d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineRemoved(engine);
-}
-
-bool QQmlDebugServer::addService(QQmlDebugService *service)
-{
- Q_D(QQmlDebugServer);
-
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != thread());
-
- connect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
- connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
-
-
- QWriteLocker lock(&d->pluginsLock);
- if (!service || d->plugins.contains(service->name()))
- return false;
- d->plugins.insert(service->name(), service);
- d->advertisePlugins();
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(service->name()))
- newState = QQmlDebugService::Enabled;
- service->d_func()->state = newState;
- return true;
-}
-
-bool QQmlDebugServer::removeService(QQmlDebugService *service)
-{
- Q_D(QQmlDebugServer);
-
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != thread());
-
- QWriteLocker lock(&d->pluginsLock);
- QQmlDebugService::State newState = QQmlDebugService::NotConnected;
-
- d->changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(this, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, newState));
-
- if (!service || !d->plugins.contains(service->name()))
- return false;
- d->plugins.remove(service->name());
-
- d->advertisePlugins();
-
- return true;
-}
-
-void QQmlDebugServer::sendMessages(QQmlDebugService *service,
- const QList<QByteArray> &messages)
-{
- QList<QByteArray> prefixedMessages;
- foreach (const QByteArray &message, messages) {
- QByteArray prefixed;
- QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
- out << service->name() << message;
- prefixedMessages << prefixed;
- }
-
- QMetaObject::invokeMethod(this, "_q_sendMessages", Qt::QueuedConnection,
- Q_ARG(QList<QByteArray>, prefixedMessages));
-}
-
-bool QQmlDebugServer::enable(int portFrom, int portTo, bool block, const QString &hostAddress)
-{
-#ifndef QT_NO_QML_DEBUGGER
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (!wrapper)
- return false;
- QQmlDebugServerPrivate *d = wrapper->m_instance.d_func();
- if (d->thread)
- return false;
- if (!d->start(portFrom, portTo, block, hostAddress, QLatin1String("qmldbg_tcp")))
- return false;
- while (!wrapper->m_instance.hasConnection()) {
- if (!wrapper->m_instance.hasThread())
- return false;
- }
- return true;
-#else
- Q_UNUSED(portFrom);
- Q_UNUSED(portTo);
- Q_UNUSED(block);
- Q_UNUSED(hostAddress);
- return false;
-#endif
-}
-
-void QQmlDebugServer::wakeEngine(QQmlEngine *engine)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == thread());
-
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
- d->engineConditions[engine].wake();
-}
-
-bool QQmlDebugServerPrivate::EngineCondition::waitForServices(QReadWriteLock *locked, int num)
-{
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != QQmlDebugServer::instance()->thread());
-
- Q_ASSERT_X(numServices == 0, Q_FUNC_INFO, "Request to wait again before previous wait finished");
- numServices = num;
- return condition->wait(locked);
-}
-
-void QQmlDebugServerPrivate::EngineCondition::wake()
-{
- if (--numServices == 0)
- condition->wakeAll();
- Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services.");
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmldebugserver_p.cpp"
diff --git a/src/qml/debugger/qqmldebugserver_p.h b/src/qml/debugger/qqmldebugserver_p.h
deleted file mode 100644
index b2bd0b2463..0000000000
--- a/src/qml/debugger/qqmldebugserver_p.h
+++ /dev/null
@@ -1,104 +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 QQMLDEBUGSERVER_H
-#define QQMLDEBUGSERVER_H
-
-#include <QtQml/qtqmlglobal.h>
-#include <private/qqmldebugserverconnection_p.h>
-#include <private/qqmldebugservice_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.
-//
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlDebugServerPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlDebugServer : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlDebugServer)
- Q_DISABLE_COPY(QQmlDebugServer)
-public:
-
- static QQmlDebugServer *instance();
-
- bool hasThread() const;
- bool hasConnection() const;
- bool hasDebuggingClient() const;
- bool blockingMode() const;
-
- QList<QQmlDebugService*> services() const;
- QStringList serviceNames() const;
-
- void addEngine(QQmlEngine *engine);
- void removeEngine(QQmlEngine *engine);
-
- bool addService(QQmlDebugService *service);
- bool removeService(QQmlDebugService *service);
-
- 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);
-
-private:
- friend class QQmlDebugService;
- friend class QQmlDebugServicePrivate;
- friend class QQmlDebugServerThread;
- friend struct QQmlDebugServerInstanceWrapper;
- QQmlDebugServer();
- Q_PRIVATE_SLOT(d_func(), void _q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State state))
- Q_PRIVATE_SLOT(d_func(), void _q_sendMessages(QList<QByteArray>))
- Q_PRIVATE_SLOT(d_func(), void _q_removeThread())
-
-public:
- static int s_dataStreamVersion;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLDEBUGSERVICE_H
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index b37a7335a0..0b07f320ec 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -32,8 +32,7 @@
****************************************************************************/
#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
-#include "qqmldebugserver_p.h"
+#include "qqmldebugconnector_p.h"
#include <private/qqmldata_p.h>
#include <private/qqmlcontext_p.h>
@@ -43,58 +42,55 @@
QT_BEGIN_NAMESPACE
-QQmlDebugServicePrivate::QQmlDebugServicePrivate()
-{
-}
+class QQmlDebugServer;
-QQmlDebugService::QQmlDebugService(const QString &name, float version, QObject *parent)
- : QObject(*(new QQmlDebugServicePrivate), parent)
+class QQmlDebugServicePrivate : public QObjectPrivate
{
- QQmlDebugServer::instance(); // create it when it isn't there yet.
+ Q_DECLARE_PUBLIC(QQmlDebugService)
+public:
+ QQmlDebugServicePrivate(const QString &name, float version);
- Q_D(QQmlDebugService);
- d->name = name;
- d->version = version;
- d->state = QQmlDebugService::NotConnected;
-}
+ const QString name;
+ const float version;
+ QQmlDebugService::State state;
+};
-QQmlDebugService::QQmlDebugService(QQmlDebugServicePrivate &dd,
- const QString &name, float version, QObject *parent)
- : QObject(dd, parent)
+QQmlDebugServicePrivate::QQmlDebugServicePrivate(const QString &name, float version) :
+ name(name), version(version), state(QQmlDebugService::NotConnected)
{
- Q_D(QQmlDebugService);
- d->name = name;
- d->version = version;
- d->state = QQmlDebugService::NotConnected;
}
-/**
- Registers the service. This should be called in the constructor of the inherited class. From
- then on the service might get asynchronous calls to messageReceived().
- */
-QQmlDebugService::State QQmlDebugService::registerService()
+QQmlDebugService::QQmlDebugService(const QString &name, float version, QObject *parent)
+ : QObject(*(new QQmlDebugServicePrivate(name, version)), parent)
{
Q_D(QQmlDebugService);
- QQmlDebugServer *server = QQmlDebugServer::instance();
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
if (!server)
- return NotConnected;
+ return;
- if (server->serviceNames().contains(d->name)) {
+ if (server->service(d->name)) {
qWarning() << "QQmlDebugService: Conflicting plugin name" << d->name;
} else {
- server->addService(this);
+ server->addService(d->name, this);
}
- return state();
}
QQmlDebugService::~QQmlDebugService()
{
- if (QQmlDebugServer *inst = QQmlDebugServer::instance())
- inst->removeService(this);
+ Q_D(QQmlDebugService);
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
+
+ if (!server)
+ return;
+
+ if (server->service(d->name) != this)
+ qWarning() << "QQmlDebugService: Plugin" << d->name << "is not registered.";
+ else
+ server->removeService(d->name);
}
-QString QQmlDebugService::name() const
+const QString &QQmlDebugService::name() const
{
Q_D(const QQmlDebugService);
return d->name;
@@ -112,27 +108,38 @@ QQmlDebugService::State QQmlDebugService::state() const
return d->state;
}
-namespace {
-
-struct ObjectReference
+void QQmlDebugService::setState(QQmlDebugService::State newState)
{
- QPointer<QObject> object;
- int id;
-};
+ Q_D(QQmlDebugService);
+ d->state = newState;
+}
-struct ObjectReferenceHash
+namespace {
+class ObjectReferenceHash : public QObject
{
+ Q_OBJECT
+public:
ObjectReferenceHash() : nextId(0) {}
- QHash<QObject *, ObjectReference> objects;
+ QHash<QObject *, int> objects;
QHash<int, QObject *> ids;
int nextId;
-};
+private slots:
+ void remove(QObject *obj);
+};
}
Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash)
+void ObjectReferenceHash::remove(QObject *obj)
+{
+ QHash<QObject *, int>::Iterator iter = objects.find(obj);
+ if (iter != objects.end()) {
+ ids.remove(iter.value());
+ objects.erase(iter);
+ }
+}
/*!
Returns a unique id for \a object. Calling this method multiple times
@@ -144,158 +151,23 @@ int QQmlDebugService::idForObject(QObject *object)
return -1;
ObjectReferenceHash *hash = objectReferenceHash();
- QHash<QObject *, ObjectReference>::Iterator iter =
- hash->objects.find(object);
+ QHash<QObject *, int>::Iterator iter = hash->objects.find(object);
if (iter == hash->objects.end()) {
int id = hash->nextId++;
-
- hash->ids.insert(id, object);
- iter = hash->objects.insert(object, ObjectReference());
- iter->object = object;
- iter->id = id;
- } else if (iter->object != object) {
- int id = hash->nextId++;
-
- hash->ids.remove(iter->id);
-
hash->ids.insert(id, object);
- iter->object = object;
- iter->id = id;
- }
- return iter->id;
-}
-
-/*!
- Returns the object for unique \a id. If the object has not previously been
- assigned an id, through idForObject(), then 0 is returned. If the object
- has been destroyed, 0 is returned.
-*/
-QObject *QQmlDebugService::objectForId(int id)
-{
- ObjectReferenceHash *hash = objectReferenceHash();
-
- QHash<int, QObject *>::Iterator iter = hash->ids.find(id);
- if (iter == hash->ids.end())
- return 0;
-
-
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- hash->ids.erase(iter);
- hash->objects.erase(objIter);
- // run a loop to remove other invalid objects
- removeInvalidObjectsFromHash();
- return 0;
- } else {
- return *iter;
+ iter = hash->objects.insert(object, id);
+ connect(object, SIGNAL(destroyed(QObject*)), hash, SLOT(remove(QObject*)));
}
+ return iter.value();
}
/*!
- Returns a list of objects matching the given filename, line and column.
+ Returns the mapping of objects to unique \a ids, created through calls to idForObject().
*/
-QList<QObject*> QQmlDebugService::objectForLocationInfo(const QString &filename,
- int lineNumber, int columnNumber)
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- QList<QObject*> objects;
- QHash<int, QObject *>::Iterator iter = hash->ids.begin();
- while (iter != hash->ids.end()) {
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- iter = hash->ids.erase(iter);
- hash->objects.erase(objIter);
- } else {
- QQmlData *ddata = QQmlData::get(iter.value());
- if (ddata && ddata->outerContext) {
- if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
- ddata->lineNumber == lineNumber &&
- ddata->columnNumber >= columnNumber) {
- objects << *iter;
- }
- }
- ++iter;
- }
- }
- return objects;
-}
-
-void QQmlDebugService::removeInvalidObjectsFromHash()
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- QHash<int, QObject *>::Iterator iter = hash->ids.begin();
- while (iter != hash->ids.end()) {
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- iter = hash->ids.erase(iter);
- hash->objects.erase(objIter);
- } else {
- ++iter;
- }
- }
-}
-
-void QQmlDebugService::clearObjectsFromHash()
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- hash->ids.clear();
- hash->objects.clear();
-}
-
-bool QQmlDebugService::isDebuggingEnabled()
-{
- return QQmlDebugServer::instance() != 0;
-}
-
-bool QQmlDebugService::hasDebuggingClient()
+const QHash<int, QObject *> &QQmlDebugService::objectsForIds()
{
- return QQmlDebugServer::instance() != 0
- && QQmlDebugServer::instance()->hasDebuggingClient();
-}
-
-bool QQmlDebugService::blockingMode()
-{
- return QQmlDebugServer::instance() != 0
- && QQmlDebugServer::instance()->blockingMode();
-}
-
-QString QQmlDebugService::objectToString(QObject *obj)
-{
- if(!obj)
- return QStringLiteral("NULL");
-
- QString objectName = obj->objectName();
- if(objectName.isEmpty())
- objectName = QStringLiteral("<unnamed>");
-
- QString rv = QString::fromUtf8(obj->metaObject()->className()) +
- QLatin1String(": ") + objectName;
-
- return rv;
-}
-
-void QQmlDebugService::sendMessage(const QByteArray &message)
-{
- sendMessages(QList<QByteArray>() << message);
-}
-
-void QQmlDebugService::sendMessages(const QList<QByteArray> &messages)
-{
- if (state() != Enabled)
- return;
-
- if (QQmlDebugServer *inst = QQmlDebugServer::instance())
- inst->sendMessages(this, messages);
+ return objectReferenceHash()->ids;
}
void QQmlDebugService::stateAboutToBeChanged(State)
@@ -328,28 +200,32 @@ void QQmlDebugService::engineRemoved(QQmlEngine *)
{
}
+int QQmlDebugStream::s_dataStreamVersion = QDataStream::Qt_4_7;
+
QQmlDebugStream::QQmlDebugStream()
: QDataStream()
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(QIODevice *d)
: QDataStream(d)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags)
: QDataStream(ba, flags)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(const QByteArray &ba)
: QDataStream(ba)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QT_END_NAMESPACE
+
+#include "qqmldebugservice.moc"
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 9cdfc34ff1..3d692133cc 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -35,7 +35,8 @@
#define QQMLDEBUGSERVICE_H
#include <QtCore/qobject.h>
-#include <QtCore/QDataStream>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qhash.h>
#include <private/qtqmlglobal_p.h>
@@ -62,35 +63,14 @@ 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;
+ const QString &name() const;
float version() const;
enum State { NotConnected, Unavailable, Enabled };
State state() const;
-
- void sendMessage(const QByteArray &);
- void sendMessages(const QList<QByteArray> &);
-
- static int idForObject(QObject *);
- static QObject *objectForId(int);
- static QList<QObject*> objectForLocationInfo(const QString &filename,
- int lineNumber, int columnNumber);
- static void removeInvalidObjectsFromHash();
- static void clearObjectsFromHash();
-
- static QString objectToString(QObject *obj);
-
- static bool isDebuggingEnabled();
- static bool hasDebuggingClient();
- static bool blockingMode();
-
-protected:
- QQmlDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
-
- State registerService();
+ void setState(State newState);
virtual void stateAboutToBeChanged(State);
virtual void stateChanged(State);
@@ -101,18 +81,26 @@ protected:
virtual void engineAdded(QQmlEngine *);
virtual void engineRemoved(QQmlEngine *);
+ static const QHash<int, QObject *> &objectsForIds();
+ static int idForObject(QObject *);
+ static QObject *objectForId(int id) { return objectsForIds().value(id); }
+
+protected:
+ explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
+
signals:
void attachedToEngine(QQmlEngine *);
void detachedFromEngine(QQmlEngine *);
-private:
- friend class QQmlDebugServer;
- friend class QQmlDebugServerPrivate;
+ void messageToClient(const QString &name, const QByteArray &message);
+ void messagesToClient(const QString &name, const QList<QByteArray> &messages);
};
class Q_QML_PRIVATE_EXPORT QQmlDebugStream : public QDataStream
{
public:
+ static int s_dataStreamVersion;
+
QQmlDebugStream();
explicit QQmlDebugStream(QIODevice *d);
QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags);
diff --git a/src/qml/debugger/qqmldebugservice_p_p.h b/src/qml/debugger/qqmldebugservicefactory_p.h
index 7d60739f3a..af50cd4635 100644
--- a/src/qml/debugger/qqmldebugservice_p_p.h
+++ b/src/qml/debugger/qqmldebugservicefactory_p.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLDEBUGSERVICE_P_H
-#define QQMLDEBUGSERVICE_P_H
+#ifndef QQMLDEBUGSERVICEFACTORY_P_H
+#define QQMLDEBUGSERVICEFACTORY_P_H
//
// W A R N I N G
@@ -45,25 +45,19 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
-#include <private/qobject_p.h>
+#include "qqmldebugservice_p.h"
QT_BEGIN_NAMESPACE
-
-class QQmlDebugServer;
-
-class QQmlDebugServicePrivate : public QObjectPrivate
+class Q_QML_PRIVATE_EXPORT QQmlDebugServiceFactory : public QObject
{
- Q_DECLARE_PUBLIC(QQmlDebugService)
+ Q_OBJECT
public:
- QQmlDebugServicePrivate();
-
- QString name;
- float version;
- QQmlDebugService::State state;
+ virtual QQmlDebugService *create(const QString &key) = 0;
};
+#define QQmlDebugServiceFactory_iid "org.qt-project.Qt.QQmlDebugServiceFactory"
+
QT_END_NAMESPACE
-#endif // QQMLDEBUGSERVICE_P_H
+#endif // QQMLDEBUGSERVICEFACTORY_P_H
diff --git a/src/qml/jsruntime/qv4qmlextensions_p.h b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
index e4b9f75298..2bf9f2785c 100644
--- a/src/qml/jsruntime/qv4qmlextensions_p.h
+++ b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
@@ -30,29 +30,14 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QV4QMLEXTENSIONS_P_H
-#define QV4QMLEXTENSIONS_P_H
-#include <qtqmlglobal.h>
-#include <qv4global_p.h>
+#include "qqmldebugserviceinterfaces_p.h"
QT_BEGIN_NAMESPACE
-namespace QV4 {
-
-struct Q_QML_EXPORT QmlExtensions
-{
- QmlExtensions()
- : valueTypeWrapperPrototype(0)
- {}
-
- Heap::Object *valueTypeWrapperPrototype;
-
- void markObjects(ExecutionEngine *e);
-};
-
-} // namespace QV4
+const QString QV4DebugService::s_key = QStringLiteral("V8Debugger");
+const QString QQmlEngineDebugService::s_key = QStringLiteral("QmlDebugger");
+const QString QQmlInspectorService::s_key = QStringLiteral("QmlInspector");
+const QString QQmlProfilerService::s_key = QStringLiteral("CanvasFrameRate");
QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
new file mode 100644
index 0000000000..a2ba670608
--- /dev/null
+++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** 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 QQMLDEBUGSERVICEINTERFACES_P_H
+#define QQMLDEBUGSERVICEINTERFACES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qstring.h>
+#include <private/qtqmlglobal_p.h>
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugstatesdelegate_p.h>
+#include <private/qqmlabstractprofileradapter_p.h>
+#include <private/qqmlboundsignal_p.h>
+
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QML_PRIVATE_EXPORT QV4DebugService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void signalEmitted(const QString &signal) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QV4DebugService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlProfilerService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
+ virtual void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
+
+ virtual void startProfiling(QQmlEngine *engine,
+ quint64 features = std::numeric_limits<quint64>::max()) = 0;
+ virtual void stopProfiling(QQmlEngine *engine) = 0;
+
+ virtual void dataReady(QQmlAbstractProfilerAdapter *profiler) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlProfilerService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void objectCreated(QQmlEngine *engine, QObject *object) = 0;
+ virtual void setStatesDelegate(QQmlDebugStatesDelegate *) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlEngineDebugService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; }
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlInspectorService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void addView(QObject *) = 0;
+ virtual void removeView(QObject *) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlInspectorService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGSERVICEINTERFACES_P_H
+
diff --git a/src/qml/debugger/qqmlinspectorservice.cpp b/src/qml/debugger/qqmlinspectorservice.cpp
deleted file mode 100644
index 5a8c4487d9..0000000000
--- a/src/qml/debugger/qqmlinspectorservice.cpp
+++ /dev/null
@@ -1,181 +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$
-**
-****************************************************************************/
-
-#include "qqmlinspectorservice_p.h"
-#include "qqmlinspectorinterface_p.h"
-#include "qqmldebugserver_p.h"
-
-#include <private/qqmlglobal_p.h>
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QPluginLoader>
-
-// print detailed information about loading of plugins
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QQmlInspectorService, serviceInstance)
-
-QQmlInspectorService::QQmlInspectorService()
- : QQmlDebugService(QStringLiteral("QmlInspector"), 1)
- , m_currentInspectorPlugin(0)
-{
- registerService();
-}
-
-QQmlInspectorService *QQmlInspectorService::instance()
-{
- return serviceInstance();
-}
-
-void QQmlInspectorService::addView(QObject *view)
-{
- m_views.append(view);
- updateState();
-}
-
-void QQmlInspectorService::removeView(QObject *view)
-{
- m_views.removeAll(view);
- updateState();
-}
-
-void QQmlInspectorService::sendMessage(const QByteArray &message)
-{
- if (state() != Enabled)
- return;
-
- QQmlDebugService::sendMessage(message);
-}
-
-void QQmlInspectorService::stateChanged(State /*state*/)
-{
- QMetaObject::invokeMethod(this, "updateState", Qt::QueuedConnection);
-}
-
-void QQmlInspectorService::updateState()
-{
- if (m_views.isEmpty()) {
- if (m_currentInspectorPlugin) {
- m_currentInspectorPlugin->deactivate();
- m_currentInspectorPlugin = 0;
- }
- return;
- }
-
- if (state() == Enabled) {
- if (m_inspectorPlugins.isEmpty())
- loadInspectorPlugins();
-
- if (m_inspectorPlugins.isEmpty()) {
- qWarning() << "QQmlInspector: No plugins found.";
- QQmlDebugServer::instance()->removeService(this);
- return;
- }
-
- m_currentInspectorPlugin = 0;
- foreach (QQmlInspectorInterface *inspector, m_inspectorPlugins) {
- if (inspector->canHandleView(m_views.first())) {
- m_currentInspectorPlugin = inspector;
- break;
- }
- }
-
- if (!m_currentInspectorPlugin) {
- qWarning() << "QQmlInspector: No plugin available for view '" << m_views.first()->metaObject()->className() << "'.";
- return;
- }
- m_currentInspectorPlugin->activate(m_views.first());
- } else {
- if (m_currentInspectorPlugin) {
- m_currentInspectorPlugin->deactivate();
- m_currentInspectorPlugin = 0;
- }
- }
-}
-
-void QQmlInspectorService::messageReceived(const QByteArray &message)
-{
- QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
-}
-
-void QQmlInspectorService::processMessage(const QByteArray &message)
-{
- if (m_currentInspectorPlugin)
- m_currentInspectorPlugin->clientMessage(message);
-}
-
-void QQmlInspectorService::loadInspectorPlugins()
-{
- QStringList pluginCandidates;
- const QStringList paths = QCoreApplication::libraryPaths();
- foreach (const QString &libPath, paths) {
- const QDir dir(libPath + QLatin1String("/qmltooling"));
- if (dir.exists())
- foreach (const QString &pluginPath, dir.entryList(QDir::Files))
- pluginCandidates << dir.absoluteFilePath(pluginPath);
- }
-
- 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.load()) {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Error while loading: " << loader.errorString();
-
- continue;
- }
-
- QQmlInspectorInterface *inspector =
- qobject_cast<QQmlInspectorInterface*>(loader.instance());
- if (inspector) {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Plugin successfully loaded.";
- m_inspectorPlugins << inspector;
- } else {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Plugin does not implement interface QQmlInspectorInterface.";
-
- loader.unload();
- }
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index b35da8a714..a6423d769a 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -32,88 +32,13 @@
****************************************************************************/
#include "qqmlprofiler_p.h"
-#include "qqmlprofilerservice_p.h"
#include "qqmldebugservice_p.h"
QT_BEGIN_NAMESPACE
-// convert to QByteArrays that can be sent to the debug client
-// use of QDataStream can skew results
-// (see tst_qqmldebugtrace::trace() benchmark)
-void QQmlProfilerData::toByteArrays(QList<QByteArray> &messages) const
-{
- QByteArray data;
- Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
- for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
- if ((messageType & (1 << decodedMessageType)) == 0)
- continue;
-
- for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
- if ((detailType & (1 << decodedDetailType)) == 0)
- continue;
-
- //### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << time << decodedMessageType << decodedDetailType;
-
- switch (decodedMessageType) {
- case QQmlProfilerDefinitions::RangeStart:
- if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
- ds << QQmlProfilerDefinitions::QmlBinding;
- break;
- case QQmlProfilerDefinitions::RangeData:
- ds << detailString;
- break;
- case QQmlProfilerDefinitions::RangeLocation:
- ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y;
- break;
- case QQmlProfilerDefinitions::RangeEnd: break;
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
- break;
- }
- messages << data;
- data.clear();
- }
- }
-}
-
-QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
- QQmlAbstractProfilerAdapter(service)
-{
- engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
- connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
- connect(this, SIGNAL(profilingDisabledWhileWaiting()),
- engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QList<QQmlProfilerData>)),
- this, SLOT(receiveData(QList<QQmlProfilerData>)));
-}
-
-qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
-{
- while (!data.empty() && data.front().time <= until) {
- data.front().toByteArrays(messages);
- data.pop_front();
- }
- return data.empty() ? -1 : data.front().time;
-}
-
-void QQmlProfilerAdapter::receiveData(const QList<QQmlProfilerData> &new_data)
-{
- data = new_data;
- service->dataReady(this);
-}
-
-
QQmlProfiler::QQmlProfiler() : featuresEnabled(0)
{
- static int metatype = qRegisterMetaType<QList<QQmlProfilerData> >();
+ static int metatype = qRegisterMetaType<QVector<QQmlProfilerData> >();
Q_UNUSED(metatype);
m_timer.start();
}
@@ -127,16 +52,12 @@ void QQmlProfiler::stopProfiling()
{
featuresEnabled = false;
reportData();
- m_data.clear();
}
void QQmlProfiler::reportData()
{
- QList<QQmlProfilerData> result;
- result.reserve(m_data.size());
- for (int i = 0; i < m_data.size(); ++i)
- result.append(m_data[i]);
- emit dataReady(result);
+ emit dataReady(m_data);
+ m_data.clear();
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 5c994b112f..3c8337c969 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -68,8 +68,9 @@ QT_BEGIN_NAMESPACE
// This struct is somewhat dangerous to use:
// The messageType is a bit field. You can pack multiple messages into
// one object, e.g. RangeStart and RangeLocation. Each one will be read
-// independently by toByteArrays. Thus you can only pack messages if their data
-// doesn't overlap. It's up to you to figure that out.
+// independently when converting to QByteArrays. Thus you can only pack
+// messages if their data doesn't overlap. It's up to you to figure that
+// out.
struct Q_AUTOTEST_EXPORT QQmlProfilerData
{
QQmlProfilerData() {}
@@ -103,8 +104,6 @@ struct Q_AUTOTEST_EXPORT QQmlProfilerData
int x; //used by RangeLocation
int y; //used by RangeLocation
-
- void toByteArrays(QList<QByteArray> &messages) const;
};
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
@@ -171,24 +170,11 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QQmlProfilerData> &);
+ void dataReady(const QVector<QQmlProfilerData> &);
protected:
QElapsedTimer m_timer;
- QVarLengthArray<QQmlProfilerData> m_data;
-};
-
-class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
- Q_OBJECT
-public:
- QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
-
-public slots:
- void receiveData(const QList<QQmlProfilerData> &new_data);
-
-private:
- QList<QQmlProfilerData> data;
+ QVector<QQmlProfilerData> m_data;
};
//
@@ -332,6 +318,6 @@ private:
};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QList<QQmlProfilerData>)
+Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
#endif // QQMLPROFILER_P_H
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
deleted file mode 100644
index cefb29e031..0000000000
--- a/src/qml/debugger/qv4debugservice.cpp
+++ /dev/null
@@ -1,1265 +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$
-**
-****************************************************************************/
-
-#include "qv4debugservice_p.h"
-#include "qqmlconfigurabledebugservice_p_p.h"
-#include "qqmlengine.h"
-#include "qv4debugging_p.h"
-#include "qv4engine_p.h"
-#include "qv4function_p.h"
-#include "qqmldebugserver_p.h"
-
-#include <private/qv8engine_p.h>
-
-#include <QtCore/QJsonArray>
-#include <QtCore/QJsonDocument>
-#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";
-
-#define NO_PROTOCOL_TRACING
-#ifdef NO_PROTOCOL_TRACING
-# define TRACE_PROTOCOL(x)
-#else
-#include <QtCore/QDebug>
-# define TRACE_PROTOCOL(x) x
-#endif
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QV4DebugService, v4ServiceInstance)
-
-class QV4DebugServicePrivate;
-
-class QV4DebuggerAgent : public QV4::Debugging::DebuggerAgent
-{
-public:
- QV4DebuggerAgent(QV4DebugServicePrivate *debugServicePrivate)
- : debugServicePrivate(debugServicePrivate)
- {}
-
- QV4::Debugging::Debugger *firstDebugger() const
- {
- // Currently only 1 single engine is supported, so:
- if (m_debuggers.isEmpty())
- return 0;
- else
- return m_debuggers.first();
- }
-
- bool isRunning() const
- {
- // Currently only 1 single engine is supported, so:
- if (QV4::Debugging::Debugger *debugger = firstDebugger())
- return debugger->state() == QV4::Debugging::Debugger::Running;
- else
- return false;
- }
-
-public slots:
- virtual void debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason);
- virtual void sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr);
-
-private:
- QV4DebugServicePrivate *debugServicePrivate;
-};
-
-class V8CommandHandler;
-class UnknownV8CommandHandler;
-
-class VariableCollector: public QV4::Debugging::Debugger::Collector
-{
-public:
- VariableCollector(QV4::ExecutionEngine *engine)
- : Collector(engine)
- , destination(0)
- {}
-
- virtual ~VariableCollector() {}
-
- void collectScope(QJsonArray *dest, QV4::Debugging::Debugger *debugger, int frameNr, int scopeNr)
- {
- qSwap(destination, dest);
- bool oldIsProp = isProperty();
- setIsProperty(true);
- debugger->collectArgumentsInContext(this, frameNr, scopeNr);
- debugger->collectLocalsInContext(this, frameNr, scopeNr);
- setIsProperty(oldIsProp);
- qSwap(destination, dest);
- }
-
- void setDestination(QJsonArray *dest)
- { destination = dest; }
-
- QJsonArray retrieveRefsToInclude()
- {
- QJsonArray result;
- qSwap(refsToInclude, result);
- return result;
- }
-
- QJsonValue lookup(int handle, bool addRefs = true)
- {
- if (handle < 0)
- handle = -handle;
-
- if (addRefs)
- foreach (int ref, refsByHandle[handle])
- refsToInclude.append(lookup(ref, false));
- return refs[handle];
- }
-
- QJsonObject makeRef(int refId)
- {
- QJsonObject ref;
- ref[QLatin1String("ref")] = refId;
- return ref;
- }
-
- QJsonObject addFunctionRef(const QString &name)
- {
- const int refId = newRefId();
-
- QJsonObject func;
- func[QLatin1String("handle")] = refId;
- func[QLatin1String("type")] = QStringLiteral("function");
- func[QLatin1String("className")] = QStringLiteral("Function");
- func[QLatin1String("name")] = name;
- insertRef(func, refId);
-
- return makeRef(refId);
- }
-
- QJsonObject addScriptRef(const QString &name)
- {
- const int refId = newRefId();
-
- QJsonObject func;
- func[QLatin1String("handle")] = refId;
- func[QLatin1String("type")] = QStringLiteral("script");
- func[QLatin1String("name")] = name;
- insertRef(func, refId);
-
- return makeRef(refId);
- }
-
- QJsonObject addObjectRef(QJsonObject obj, bool anonymous)
- {
- int ref = newRefId();
-
- if (anonymous)
- ref = -ref;
- obj[QLatin1String("handle")] = ref;
- obj[QLatin1String("type")] = QStringLiteral("object");
- insertRef(obj, ref);
- QSet<int> used;
- qSwap(usedRefs, used);
- refsByHandle.insert(ref, used);
-
- return makeRef(ref);
- }
-
-protected:
- virtual void addUndefined(const QString &name)
- {
- QJsonObject o;
- addHandle(name, o, QStringLiteral("undefined"));
- }
-
- virtual void addNull(const QString &name)
- {
- QJsonObject o;
- addHandle(name, o, QStringLiteral("null"));
- }
-
- virtual void addBoolean(const QString &name, bool value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("boolean"));
- }
-
- virtual void addString(const QString &name, const QString &value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("string"));
- }
-
- virtual void addObject(const QString &name, const QV4::Value &value)
- {
- QV4::Scope scope(engine());
- QV4::ScopedObject obj(scope, value.asObject());
-
- int ref = cachedObjectRef(obj);
- if (ref != -1) {
- addNameRefPair(name, ref);
- } else {
- int ref = newRefId();
- cacheObjectRef(obj, ref);
-
- QJsonArray properties, *prev = &properties;
- QSet<int> used;
- qSwap(usedRefs, used);
- qSwap(destination, prev);
- collect(obj);
- qSwap(destination, prev);
- qSwap(usedRefs, used);
-
- QJsonObject o;
- o[QLatin1String("properties")] = properties;
- addHandle(name, o, QStringLiteral("object"), ref);
- refsByHandle.insert(ref, used);
- }
- }
-
- virtual void addInteger(const QString &name, int value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("number"));
- }
-
- virtual void addDouble(const QString &name, double value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("number"));
- }
-
-private:
- int addHandle(const QString &name, QJsonObject object, const QString &type, int suppliedRef = -1)
- {
- Q_ASSERT(destination);
-
- object[QLatin1String("type")] = type;
-
- QJsonDocument tmp;
- tmp.setObject(object);
- QByteArray key = tmp.toJson(QJsonDocument::Compact);
-
- int ref;
- if (suppliedRef == -1) {
- ref = refCache.value(key, -1);
- if (ref == -1) {
- ref = newRefId();
- object[QLatin1String("handle")] = ref;
- insertRef(object, ref);
- refCache.insert(key, ref);
- }
- } else {
- ref = suppliedRef;
- object[QLatin1String("handle")] = ref;
- insertRef(object, ref);
- refCache.insert(key, ref);
- }
-
- addNameRefPair(name, ref);
- return ref;
- }
-
- void addNameRefPair(const QString &name, int ref)
- {
- QJsonObject nameValuePair;
- nameValuePair[QLatin1String("name")] = name;
- if (isProperty()) {
- nameValuePair[QLatin1String("ref")] = ref;
- } else {
- QJsonObject refObj;
- refObj[QLatin1String("ref")] = ref;
- nameValuePair[QLatin1String("value")] = refObj;
- }
- destination->append(nameValuePair);
- usedRefs.insert(ref);
- }
-
- int newRefId()
- {
- int ref = refs.count();
- refs.insert(ref, QJsonValue());
- return ref;
- }
-
- void insertRef(const QJsonValue &value, int refId)
- {
- if (refId < 0)
- refId = -refId;
-
- refs.insert(refId, value);
- refsToInclude.append(value);
- }
-
- void cacheObjectRef(QV4::Value obj, int ref)
- {
- objectRefs.insert(obj.val, ref);
- }
-
- int cachedObjectRef(QV4::Value obj) const
- {
- return objectRefs.value(obj.val, -1);
- }
-
-private:
- QJsonArray refsToInclude;
- QHash<int, QJsonValue> refs;
- QHash<QByteArray, int> refCache;
- QJsonArray *destination;
- QSet<int> usedRefs;
- QHash<int, QSet<int> > refsByHandle;
- QHash<quint64, int> objectRefs;
-};
-
-class QV4DebugServicePrivate : public QQmlConfigurableDebugServicePrivate
-{
- Q_DECLARE_PUBLIC(QV4DebugService)
-
-public:
- QV4DebugServicePrivate();
- ~QV4DebugServicePrivate() { qDeleteAll(handlers.values()); }
-
- static QByteArray packMessage(const QByteArray &command, const QByteArray &message = QByteArray())
- {
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
- static const QByteArray cmd("V8DEBUG");
- rs << cmd << command << message;
- return reply;
- }
-
- void send(QJsonObject v8Payload)
- {
- v8Payload[QLatin1String("seq")] = sequence++;
- QJsonDocument doc;
- doc.setObject(v8Payload);
-#ifdef NO_PROTOCOL_TRACING
- QByteArray responseData = doc.toJson(QJsonDocument::Compact);
-#else
- QByteArray responseData = doc.toJson(QJsonDocument::Indented);
-#endif
-
- TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData << endl);
-
- q_func()->sendMessage(packMessage("v8message", responseData));
- }
-
- void processCommand(const QByteArray &command, const QByteArray &data);
-
- QV4DebuggerAgent debuggerAgent;
-
- QStringList breakOnSignals;
- QMap<int, QV4::Debugging::Debugger *> debuggerMap;
- static int debuggerIndex;
- static int sequence;
- const int version;
-
- V8CommandHandler *v8CommandHandler(const QString &command) const;
-
- void clearHandles(QV4::ExecutionEngine *engine)
- {
- theCollector.reset(new VariableCollector(engine));
- }
-
- QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
- QV4::Debugging::Debugger *debugger)
- {
- QJsonObject frame;
- frame[QLatin1String("index")] = frameNr;
- frame[QLatin1String("debuggerFrame")] = false;
- frame[QLatin1String("func")] = theCollector->addFunctionRef(stackFrame.function);
- frame[QLatin1String("script")] = theCollector->addScriptRef(stackFrame.source);
- frame[QLatin1String("line")] = stackFrame.line - 1;
- if (stackFrame.column >= 0)
- frame[QLatin1String("column")] = stackFrame.column;
-
- QJsonArray properties;
- theCollector->setDestination(&properties);
- if (debugger->collectThisInContext(theCollector.data(), frameNr)) {
- QJsonObject obj;
- obj[QLatin1String("properties")] = properties;
- frame[QLatin1String("receiver")] = theCollector->addObjectRef(obj, false);
- }
-
- QJsonArray scopes;
- // Only type and index are used by Qt Creator, so we keep it easy:
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
- int type = encodeScopeType(scopeTypes[i]);
- if (type == -1)
- continue;
-
- QJsonObject scope;
- scope[QLatin1String("index")] = i;
- scope[QLatin1String("type")] = type;
- scopes.push_back(scope);
- }
- frame[QLatin1String("scopes")] = scopes;
-
- return frame;
- }
-
- int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
- {
- switch (scopeType) {
- case QV4::Heap::ExecutionContext::Type_GlobalContext:
- return 0;
- break;
- case QV4::Heap::ExecutionContext::Type_CatchContext:
- return 4;
- break;
- case QV4::Heap::ExecutionContext::Type_WithContext:
- return 2;
- break;
- case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
- case QV4::Heap::ExecutionContext::Type_CallContext:
- return 1;
- break;
- case QV4::Heap::ExecutionContext::Type_QmlContext:
- default:
- return -1;
- }
- }
-
- QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::Debugger *debugger)
- {
- QJsonObject scope;
-
- QJsonArray properties;
- theCollector->collectScope(&properties, debugger, frameNr, scopeNr);
-
- QJsonObject anonymous;
- anonymous[QLatin1String("properties")] = properties;
-
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
- scope[QLatin1String("index")] = scopeNr;
- scope[QLatin1String("frameIndex")] = frameNr;
- scope[QLatin1String("object")] = theCollector->addObjectRef(anonymous, true);
-
- return scope;
- }
-
- QJsonValue lookup(int refId) const { return theCollector->lookup(refId); }
-
- QJsonArray buildRefs()
- {
- return theCollector->retrieveRefsToInclude();
- }
-
- VariableCollector *collector() const
- {
- return theCollector.data();
- }
-
- void selectFrame(int frameNr)
- { theSelectedFrame = frameNr; }
-
- int selectedFrame() const
- { return theSelectedFrame; }
-
-private:
- QScopedPointer<VariableCollector> theCollector;
- int theSelectedFrame;
-
- void addHandler(V8CommandHandler* handler);
- QHash<QString, V8CommandHandler*> handlers;
- QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler;
-};
-
-int QV4DebugServicePrivate::debuggerIndex = 0;
-int QV4DebugServicePrivate::sequence = 0;
-
-class V8CommandHandler
-{
-public:
- V8CommandHandler(const QString &command)
- : cmd(command)
- {}
-
- virtual ~V8CommandHandler()
- {}
-
- QString command() const { return cmd; }
-
- void handle(const QJsonObject &request, QQmlDebugService *s, QV4DebugServicePrivate *p)
- {
- TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
-
- req = request;
- seq = req.value(QStringLiteral("seq"));
- debugService = s;
- debugServicePrivate = p;
-
- handleRequest();
- if (!response.isEmpty()) {
- response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
- }
-
- debugServicePrivate = 0;
- debugService = 0;
- seq = QJsonValue();
- req = QJsonObject();
- response = QJsonObject();
- }
-
- virtual void handleRequest() = 0;
-
-protected:
- void addCommand() { response.insert(QStringLiteral("command"), cmd); }
- void addRequestSequence() { response.insert(QStringLiteral("request_seq"), seq); }
- void addSuccess(bool success) { response.insert(QStringLiteral("success"), success); }
- void addBody(const QJsonObject &body)
- {
- response.insert(QStringLiteral("body"), body);
- }
-
- void addRunning()
- {
- response.insert(QStringLiteral("running"), debugServicePrivate->debuggerAgent.isRunning());
- }
-
- void addRefs()
- {
- response.insert(QStringLiteral("refs"), debugServicePrivate->buildRefs());
- }
-
- void createErrorResponse(const QString &msg)
- {
- QJsonValue command = req.value(QStringLiteral("command"));
- response.insert(QStringLiteral("command"), command);
- addRequestSequence();
- addSuccess(false);
- addRunning();
- response.insert(QStringLiteral("message"), msg);
- }
-
- int requestSequenceNr() const
- { return seq.toInt(-1); }
-
-protected:
- QString cmd;
- QJsonObject req;
- QJsonValue seq;
- QQmlDebugService *debugService;
- QV4DebugServicePrivate *debugServicePrivate;
- QJsonObject response;
-};
-
-class UnknownV8CommandHandler: public V8CommandHandler
-{
-public:
- UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
-
- virtual void handleRequest()
- {
- QString msg = QStringLiteral("unimplemented command \"");
- msg += req.value(QStringLiteral("command")).toString();
- msg += QStringLiteral("\"");
- createErrorResponse(msg);
- }
-};
-
-namespace {
-class V8VersionRequest: public V8CommandHandler
-{
-public:
- V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
-
- virtual void handleRequest()
- {
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("V8Version"),
- QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
- addBody(body);
- }
-};
-
-class V8SetBreakPointRequest: public V8CommandHandler
-{
-public:
- V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
- if (args.isEmpty())
- return;
-
- QString type = args.value(QStringLiteral("type")).toString();
- if (type != QStringLiteral("scriptRegExp")) {
- createErrorResponse(QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type));
- return;
- }
-
- QString fileName = args.value(QStringLiteral("target")).toString();
- if (fileName.isEmpty()) {
- createErrorResponse(QStringLiteral("breakpoint has no file name"));
- return;
- }
-
- int line = args.value(QStringLiteral("line")).toInt(-1);
- if (line < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid line number"));
- return;
- }
-
- bool enabled = args.value(QStringLiteral("enabled")).toBool(true);
- QString condition = args.value(QStringLiteral("condition")).toString();
-
- // set the break point:
- int id = debugServicePrivate->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), type);
- body.insert(QStringLiteral("breakpoint"), id);
- // It's undocumented, but V8 sends back an actual_locations array too. However, our
- // Debugger currently doesn't tell us when it resolved a breakpoint, so we'll leave them
- // pending until the breakpoint is hit for the first time.
- addBody(body);
- }
-};
-
-class V8ClearBreakPointRequest: public V8CommandHandler
-{
-public:
- V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
- if (args.isEmpty())
- return;
-
- int id = args.value(QStringLiteral("breakpoint")).toInt(-1);
- if (id < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid number"));
- return;
- }
-
- // remove the break point:
- debugServicePrivate->debuggerAgent.removeBreakPoint(id);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), QStringLiteral("scriptRegExp"));
- body.insert(QStringLiteral("breakpoint"), id);
- addBody(body);
- }
-};
-
-class V8BacktraceRequest: public V8CommandHandler
-{
-public:
- V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
-
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- int fromFrame = arguments.value(QStringLiteral("fromFrame")).toInt(0);
- int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10);
- // no idea what the bottom property is for, so we'll ignore it.
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
-
- QJsonArray frameArray;
- QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
- for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
- frameArray.push_back(debugServicePrivate->buildFrame(frames[i], i, debugger));
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- if (frameArray.isEmpty()) {
- body.insert(QStringLiteral("totalFrames"), 0);
- } else {
- body.insert(QStringLiteral("fromFrame"), fromFrame);
- body.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
- body.insert(QStringLiteral("frames"), frameArray);
- }
- addBody(body);
- addRefs();
- }
-};
-
-class V8FrameRequest: public V8CommandHandler
-{
-public:
- V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("number")).toInt(debugServicePrivate->selectedFrame());
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
- createErrorResponse(QStringLiteral("frame command has invalid frame number"));
- return;
- }
-
- debugServicePrivate->selectFrame(frameNr);
- QJsonObject frame = debugServicePrivate->buildFrame(frames[frameNr], frameNr, debugger);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(frame);
- addRefs();
- }
-};
-
-class V8ScopeRequest: public V8CommandHandler
-{
-public:
- V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("frameNumber")).toInt(debugServicePrivate->selectedFrame());
- const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
- createErrorResponse(QStringLiteral("scope command has invalid frame number"));
- return;
- }
- if (scopeNr < 0) {
- createErrorResponse(QStringLiteral("scope command has invalid scope number"));
- return;
- }
-
- QJsonObject scope = debugServicePrivate->buildScope(frameNr, scopeNr, debugger);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(scope);
- addRefs();
- }
-};
-
-class V8LookupRequest: public V8CommandHandler
-{
-public:
- V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QJsonArray handles = arguments.value(QStringLiteral("handles")).toArray();
-
- QJsonObject body;
- foreach (QJsonValue handle, handles)
- body[QString::number(handle.toInt())] = debugServicePrivate->lookup(handle.toInt());
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(body);
- addRefs();
- }
-};
-
-class V8ContinueRequest: public V8CommandHandler
-{
-public:
- V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
-
- if (arguments.empty()) {
- debugger->resume(QV4::Debugging::Debugger::FullThrottle);
- } else {
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString stepAction = arguments.value(QStringLiteral("stepaction")).toString();
- const int stepcount = arguments.value(QStringLiteral("stepcount")).toInt(1);
- if (stepcount != 1)
- qWarning() << "Step count other than 1 is not supported.";
-
- if (stepAction == QStringLiteral("in")) {
- debugger->resume(QV4::Debugging::Debugger::StepIn);
- } else if (stepAction == QStringLiteral("out")) {
- debugger->resume(QV4::Debugging::Debugger::StepOut);
- } else if (stepAction == QStringLiteral("next")) {
- debugger->resume(QV4::Debugging::Debugger::StepOver);
- } else {
- createErrorResponse(QStringLiteral("continue command has invalid stepaction"));
- return;
- }
- }
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- }
-};
-
-class V8DisconnectRequest: public V8CommandHandler
-{
-public:
- V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
-
- virtual void handleRequest()
- {
- debugServicePrivate->debuggerAgent.removeAllBreakPoints();
- debugServicePrivate->debuggerAgent.resumeAll();
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- }
-};
-
-class V8SetExceptionBreakRequest: public V8CommandHandler
-{
-public:
- V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
-
- virtual void handleRequest()
- {
- bool wasEnabled = debugServicePrivate->debuggerAgent.breakOnThrow();
-
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString type = arguments.value(QStringLiteral("type")).toString();
- bool enabled = arguments.value(QStringLiteral("number")).toBool(!wasEnabled);
-
- if (type == QStringLiteral("all")) {
- // that's fine
- } else if (type == QStringLiteral("uncaught")) {
- createErrorResponse(QStringLiteral("breaking only on uncaught exceptions is not supported yet"));
- return;
- } else {
- createErrorResponse(QStringLiteral("invalid type for break on exception"));
- return;
- }
-
- // do it:
- debugServicePrivate->debuggerAgent.setBreakOnThrow(enabled);
-
- QJsonObject body;
- body[QLatin1String("type")] = type;
- body[QLatin1String("enabled")] = debugServicePrivate->debuggerAgent.breakOnThrow();
-
- // response:
- addBody(body);
- addRunning();
- addSuccess(true);
- addRequestSequence();
- addCommand();
- }
-};
-
-class V8ScriptsRequest: public V8CommandHandler
-{
-public:
- V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
-
- virtual void handleRequest()
- {
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- int types = arguments.value(QStringLiteral("types")).toInt(-1);
- if (types < 0 || types > 7) {
- createErrorResponse(QStringLiteral("invalid types value in scripts command"));
- return;
- } else if (types != 4) {
- createErrorResponse(QStringLiteral("unsupported types value in scripts command"));
- return;
- }
-
- // do it:
- debugServicePrivate->debuggerAgent.firstDebugger()->gatherSources(requestSequenceNr());
-
- // response will be send by
- }
-};
-
-// Request:
-// {
-// "seq": 4,
-// "type": "request",
-// "command": "evaluate",
-// "arguments": {
-// "expression": "a",
-// "frame": 0
-// }
-// }
-//
-// Response:
-// {
-// "body": {
-// "handle": 3,
-// "type": "number",
-// "value": 1
-// },
-// "command": "evaluate",
-// "refs": [],
-// "request_seq": 4,
-// "running": false,
-// "seq": 5,
-// "success": true,
-// "type": "response"
-// }
-//
-// The "value" key in "body" is the result of evaluating the expression in the request.
-class V8EvaluateRequest: public V8CommandHandler
-{
-public:
- V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
-
- virtual void handleRequest()
- {
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString expression = arguments.value(QStringLiteral("expression")).toString();
- const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- Q_ASSERT(debugger->state() == QV4::Debugging::Debugger::Paused);
-
- VariableCollector *collector = debugServicePrivate->collector();
- QJsonArray dest;
- collector->setDestination(&dest);
- debugger->evaluateExpression(frame, expression, collector);
-
- const int ref = dest.at(0).toObject().value(QStringLiteral("value")).toObject()
- .value(QStringLiteral("ref")).toInt();
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(collector->lookup(ref).toObject());
- addRefs();
- }
-};
-} // anonymous namespace
-
-QV4DebugServicePrivate::QV4DebugServicePrivate()
- : debuggerAgent(this)
- , version(1)
- , theSelectedFrame(0)
- , unknownV8CommandHandler(new UnknownV8CommandHandler)
-{
- addHandler(new V8VersionRequest);
- addHandler(new V8SetBreakPointRequest);
- addHandler(new V8ClearBreakPointRequest);
- addHandler(new V8BacktraceRequest);
- addHandler(new V8FrameRequest);
- addHandler(new V8ScopeRequest);
- addHandler(new V8LookupRequest);
- addHandler(new V8ContinueRequest);
- addHandler(new V8DisconnectRequest);
- addHandler(new V8SetExceptionBreakRequest);
- addHandler(new V8ScriptsRequest);
- addHandler(new V8EvaluateRequest);
-}
-
-void QV4DebugServicePrivate::addHandler(V8CommandHandler* handler)
-{
- handlers[handler->command()] = handler;
-}
-
-V8CommandHandler *QV4DebugServicePrivate::v8CommandHandler(const QString &command) const
-{
- V8CommandHandler *handler = handlers.value(command, 0);
- if (handler)
- return handler;
- else
- return unknownV8CommandHandler.data();
-}
-
-QV4DebugService::QV4DebugService(QObject *parent)
- : QQmlConfigurableDebugService(*(new QV4DebugServicePrivate()),
- QStringLiteral("V8Debugger"), 1, parent)
-{}
-
-QV4DebugService::~QV4DebugService()
-{
-}
-
-QV4DebugService *QV4DebugService::instance()
-{
- return v4ServiceInstance();
-}
-
-void QV4DebugService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
- if (engine) {
- QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
- if (QQmlDebugServer *server = QQmlDebugServer::instance()) {
- if (ee) {
- ee->enableDebugger();
- QV4::Debugging::Debugger *debugger = ee->debugger;
- d->debuggerMap.insert(d->debuggerIndex++, debugger);
- d->debuggerAgent.addDebugger(debugger);
- d->debuggerAgent.moveToThread(server->thread());
- moveToThread(server->thread());
- }
- }
- }
- QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
-}
-
-void QV4DebugService::engineAboutToBeRemoved(QQmlEngine *engine)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
- if (engine){
- const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
- if (ee) {
- QV4::Debugging::Debugger *debugger = ee->debugger;
- typedef QMap<int, QV4::Debugging::Debugger *>::const_iterator DebuggerMapIterator;
- const DebuggerMapIterator end = d->debuggerMap.constEnd();
- for (DebuggerMapIterator i = d->debuggerMap.constBegin(); i != end; ++i) {
- if (i.value() == debugger) {
- d->debuggerMap.remove(i.key());
- break;
- }
- }
- d->debuggerAgent.removeDebugger(debugger);
- }
- }
- QQmlConfigurableDebugService::engineAboutToBeRemoved(engine);
-}
-
-void QV4DebugService::signalEmitted(const QString &signal)
-{
- //This function is only called by QQmlBoundSignal
- //only if there is a slot connected to the signal. Hence, there
- //is no need for additional check.
- Q_D(QV4DebugService);
-
- //Parse just the name and remove the class info
- //Normalize to Lower case.
- QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
-
- foreach (const QString &signal, d->breakOnSignals) {
- if (signal == signalName) {
- // TODO: pause debugger
- break;
- }
- }
-}
-
-void QV4DebugService::messageReceived(const QByteArray &message)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
-
- QQmlDebugStream ms(message);
- QByteArray header;
- ms >> header;
-
- TRACE_PROTOCOL(qDebug() << "received message with header" << header);
-
- if (header == "V8DEBUG") {
- QByteArray type;
- QByteArray payload;
- ms >> type >> payload;
- TRACE_PROTOCOL(qDebug() << "... type:" << type);
-
- if (type == V4_CONNECT) {
- sendMessage(d->packMessage(type));
- stopWaiting();
- } else if (type == V4_PAUSE) {
- d->debuggerAgent.pauseAll();
- sendSomethingToSomebody(type);
- } else if (type == V4_BREAK_ON_SIGNAL) {
- QByteArray signal;
- bool enabled;
- ms >> signal >> enabled;
- //Normalize to lower case.
- QString signalName(QString::fromUtf8(signal).toLower());
- if (enabled)
- d->breakOnSignals.append(signalName);
- else
- d->breakOnSignals.removeOne(signalName);
- } else if (type == "v8request") {
- handleV8Request(payload);
- } else if (type == V4_DISCONNECT) {
- TRACE_PROTOCOL(qDebug() << "... payload:" << payload);
- handleV8Request(payload);
- } else {
- sendSomethingToSomebody(type, 0);
- }
- }
-}
-
-void QV4DebugService::sendSomethingToSomebody(const char *type, int magicNumber)
-{
- Q_D(QV4DebugService);
-
- QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
- rs << QByteArray(type)
- << QByteArray::number(d->version) << QByteArray::number(magicNumber);
- sendMessage(d->packMessage(type, response));
-}
-
-void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason)
-{
- Q_UNUSED(reason);
-
- debugServicePrivate->clearHandles(debugger->engine());
-
- QJsonObject event, body, script;
- event.insert(QStringLiteral("type"), QStringLiteral("event"));
-
- switch (reason) {
- case QV4::Debugging::Step:
- case QV4::Debugging::PauseRequest:
- case QV4::Debugging::BreakPoint: {
- event.insert(QStringLiteral("event"), QStringLiteral("break"));
- QVector<QV4::StackFrame> frames = debugger->stackTrace(1);
- if (frames.isEmpty())
- break;
-
- const QV4::StackFrame &topFrame = frames.first();
- body.insert(QStringLiteral("invocationText"), topFrame.function);
- body.insert(QStringLiteral("sourceLine"), topFrame.line - 1);
- if (topFrame.column > 0)
- body.insert(QStringLiteral("sourceColumn"), topFrame.column);
- QJsonArray breakPoints;
- foreach (int breakPointId, breakPointIds(topFrame.source, topFrame.line))
- breakPoints.push_back(breakPointId);
- body.insert(QStringLiteral("breakpoints"), breakPoints);
- script.insert(QStringLiteral("name"), topFrame.source);
- } break;
- case QV4::Debugging::Throwing:
- // TODO: complete this!
- event.insert(QStringLiteral("event"), QStringLiteral("exception"));
- break;
- }
-
- if (!script.isEmpty())
- body.insert(QStringLiteral("script"), script);
- if (!body.isEmpty())
- event.insert(QStringLiteral("body"), body);
- debugServicePrivate->send(event);
-}
-
-void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr)
-{
- QJsonArray body;
- foreach (const QString source, sources) {
- QJsonObject src;
- src[QLatin1String("name")] = source;
- src[QLatin1String("scriptType")] = 4;
- body.append(src);
- }
-
- QJsonObject response;
- response[QLatin1String("success")] = true;
- response[QLatin1String("running")] = debugger->state() == QV4::Debugging::Debugger::Running;
- response[QLatin1String("body")] = body;
- response[QLatin1String("command")] = QStringLiteral("scripts");
- response[QLatin1String("request_seq")] = requestSequenceNr;
- response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
-}
-
-void QV4DebugService::handleV8Request(const QByteArray &payload)
-{
- Q_D(QV4DebugService);
-
- TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload);
-
- QJsonDocument request = QJsonDocument::fromJson(payload);
- QJsonObject o = request.object();
- QJsonValue type = o.value(QStringLiteral("type"));
- if (type.toString() == QStringLiteral("request")) {
- QJsonValue command = o.value(QStringLiteral("command"));
- V8CommandHandler *h = d->v8CommandHandler(command.toString());
- if (h)
- h->handle(o, this, d);
- }
-}
-
-QT_END_NAMESPACE
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..ab74211d23 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -478,7 +478,7 @@ public:
load64(addr, dest);
} else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
}
}
@@ -491,7 +491,7 @@ public:
load64(addr, dest);
} else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
}
}
@@ -500,7 +500,7 @@ public:
Q_UNUSED(argumentNumber);
QV4::Value v = convertToValue(c);
- move(TrustedImm64(v.val), dest);
+ move(TrustedImm64(v.rawValue()), dest);
}
void loadArgumentInRegister(IR::Expr* expr, RegisterID dest, int argumentNumber)
@@ -509,7 +509,7 @@ public:
if (!expr) {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
} else if (IR::Temp *t = expr->asTemp()){
loadArgumentInRegister(t, dest, argumentNumber);
} else if (IR::ArgLocal *al = expr->asArgLocal()) {
@@ -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)
@@ -781,11 +791,11 @@ public:
void storeValue(QV4::Primitive value, Address destination)
{
#ifdef VALUE_FITS_IN_REGISTER
- store64(TrustedImm64(value.val), destination);
+ store64(TrustedImm64(value.rawValue()), destination);
#else
- store32(TrustedImm32(value.int_32), destination);
+ store32(TrustedImm32(value.int_32()), destination);
destination.offset += 4;
- store32(TrustedImm32(value.tag), destination);
+ store32(TrustedImm32(value.tag()), destination);
#endif
}
@@ -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
@@ -945,8 +957,8 @@ public:
tagAddr.offset += 4;
QV4::Primitive v = convertToValue(c);
- store32(TrustedImm32(v.int_32), addr);
- store32(TrustedImm32(v.tag), tagAddr);
+ store32(TrustedImm32(v.int_32()), addr);
+ store32(TrustedImm32(v.tag()), tagAddr);
return Pointer(addr);
}
@@ -961,7 +973,7 @@ public:
{
store32(reg, addr);
addr.offset += 4;
- store32(TrustedImm32(QV4::Primitive::fromBoolean(0).tag), addr);
+ store32(TrustedImm32(QV4::Primitive::fromBoolean(0).tag()), addr);
}
void storeBool(RegisterID src, RegisterID dest)
@@ -1005,7 +1017,7 @@ public:
{
store32(reg, addr);
addr.offset += 4;
- store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag), addr);
+ store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag()), addr);
}
void storeInt32(RegisterID reg, IR::Expr *target)
@@ -1084,7 +1096,7 @@ public:
RegisterID toInt32Register(IR::Expr *e, RegisterID scratchReg)
{
if (IR::Const *c = e->asConst()) {
- move(TrustedImm32(convertToValue(c).int_32), scratchReg);
+ move(TrustedImm32(convertToValue(c).int_32()), scratchReg);
return scratchReg;
}
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..acead2088b 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;
}
@@ -574,9 +574,9 @@ void InstructionSelection::loadThisObject(IR::Expr *temp)
#endif
}
-void InstructionSelection::loadQmlIdArray(IR::Expr *temp)
+void InstructionSelection::loadQmlContext(IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlIdArray, Assembler::EngineRegister);
+ generateFunctionCall(temp, Runtime::getQmlContext, Assembler::EngineRegister);
}
void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
@@ -584,16 +584,6 @@ void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::EngineRegister);
}
-void InstructionSelection::loadQmlContextObject(IR::Expr *temp)
-{
- generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::EngineRegister);
-}
-
-void InstructionSelection::loadQmlScopeObject(IR::Expr *temp)
-{
- generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::EngineRegister);
-}
-
void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name));
@@ -614,7 +604,7 @@ void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
_as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
} else if (targetTemp->type == IR::BoolType) {
Q_ASSERT(sourceConst->type == IR::BoolType);
- _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
+ _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32()),
(Assembler::RegisterID) targetTemp->index);
} else {
Q_UNREACHABLE();
@@ -680,6 +670,18 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::
}
}
+void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, IR::Expr *target)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(target, Runtime::getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(target, Runtime::getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else if (kind == IR::Member::MemberOfIdObjectsArray)
+ generateFunctionCall(target, Runtime::getQmlIdObject, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0)
@@ -708,6 +710,18 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
}
}
+void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(Assembler::Void, Runtime::setQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
+ Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(Assembler::Void, Runtime::setQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
+ Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
generateFunctionCall(Assembler::Void, Runtime::setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
@@ -901,6 +915,24 @@ void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr
binop.generate(leftSource, rightSource, target);
}
+void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+{
+ prepareCallData(args, base);
+
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(result, Runtime::callQmlScopeObjectProperty,
+ Assembler::EngineRegister,
+ Assembler::TrustedImm32(propertyIndex),
+ baseAddressForCallData());
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(result, Runtime::callQmlContextObjectProperty,
+ Assembler::EngineRegister,
+ Assembler::TrustedImm32(propertyIndex),
+ baseAddressForCallData());
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -1297,11 +1329,11 @@ void InstructionSelection::visitCJump(IR::CJump *s)
} else {
Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond);
Address tag = temp;
- tag.offset += qOffsetOf(QV4::Value, tag);
+ tag.offset += QV4::Value::tagOffset();
Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
Address data = temp;
- data.offset += qOffsetOf(QV4::Value, int_32);
+ data.offset += QV4::Value::valueOffset();
_as->load32(data, Assembler::ReturnValueRegister);
Assembler::Jump testBoolean = _as->jump();
@@ -1383,11 +1415,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;
@@ -1472,13 +1507,16 @@ void InstructionSelection::visitRet(IR::Ret *s)
} else if (IR::Const *c = s->expr->asConst()) {
QV4::Primitive retVal = convertToValue(c);
#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+ _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);
+ _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
#endif
} else {
Q_UNREACHABLE();
@@ -1499,13 +1537,16 @@ void InstructionSelection::visitRet(IR::Ret *s)
_as->exceptionReturnLabel = _as->label();
QV4::Primitive retVal = Primitive::undefinedValue();
#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+ _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);
+ _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
#endif
_as->jump(leaveStackFrame);
}
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 87b4a20bfc..6e842f5fb4 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -91,14 +91,13 @@ protected:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result);
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
virtual void convertType(IR::Expr *source, IR::Expr *target);
virtual void loadThisObject(IR::Expr *temp);
- virtual void loadQmlIdArray(IR::Expr *target);
+ virtual void loadQmlContext(IR::Expr *target);
virtual void loadQmlImportedScripts(IR::Expr *target);
- virtual void loadQmlContextObject(IR::Expr *target);
- virtual void loadQmlScopeObject(IR::Expr *target);
virtual void loadQmlSingleton(const QString &name, IR::Expr *target);
virtual void loadConst(IR::Const *sourceConst, IR::Expr *target);
virtual void loadString(const QString &str, IR::Expr *target);
@@ -107,8 +106,10 @@ protected:
virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
virtual void initClosure(IR::Closure *closure, IR::Expr *target);
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target);
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index ae06a99d2a..b9178c0ea0 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)
@@ -299,6 +299,16 @@ protected: // IRDecoder
addCall();
}
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+ {
+ Q_UNUSED(propertyIndex)
+
+ addDef(result);
+ addUses(base->asTemp(), Use::CouldHaveRegister);
+ addUses(args, Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -421,7 +431,7 @@ protected: // IRDecoder
addDef(temp);
}
- virtual void loadQmlIdArray(IR::Expr *temp)
+ virtual void loadQmlContext(IR::Expr *temp)
{
addDef(temp);
addCall();
@@ -433,20 +443,6 @@ protected: // IRDecoder
addCall();
}
- virtual void loadQmlContextObject(Expr *temp)
- {
- addDef(temp);
- addCall();
- }
-
- virtual void loadQmlScopeObject(Expr *temp)
- {
- Q_UNUSED(temp);
-
- addDef(temp);
- addCall();
- }
-
virtual void loadQmlSingleton(const QString &/*name*/, Expr *temp)
{
Q_UNUSED(temp);
@@ -511,6 +507,13 @@ protected: // IRDecoder
addCall();
}
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind /*kind*/, int /*propertyIndex*/)
+ {
+ addUses(source->asTemp(), Use::CouldHaveRegister);
+ addUses(targetBase->asTemp(), Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int /*propertyIndex*/)
{
addUses(source->asTemp(), Use::CouldHaveRegister);
@@ -518,6 +521,13 @@ protected: // IRDecoder
addCall();
}
+ virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, IR::Expr *target)
+ {
+ addDef(target);
+ addUses(base->asTemp(), Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target)
{
addDef(target);
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..4910b6a1c6 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());
}
@@ -581,7 +580,7 @@ QJSEnginePrivate::~QJSEnginePrivate()
QQmlPropertyCache *QJSEnginePrivate::createCache(const QMetaObject *mo)
{
if (!mo->superClass()) {
- QQmlPropertyCache *rv = new QQmlPropertyCache(q_func(), mo);
+ QQmlPropertyCache *rv = new QQmlPropertyCache(QV8Engine::getV4(q_func()), mo);
propertyCache.insert(mo, rv);
return rv;
} else {
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..39dce8efe0 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,11 +41,11 @@ 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)
{
- Q_ASSERT(vtable == QV4::ArgumentsObject::staticVTable());
+ Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
ExecutionEngine *v4 = context->d()->engine;
Scope scope(v4);
@@ -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..aab5e2c156 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
@@ -106,12 +106,12 @@ struct ArgumentsObject: Object {
Heap::MemberData *mappedArguments() { return d()->mappedArguments; }
static bool isNonStrictArgumentsObject(Managed *m) {
- return m->d()->vtable->type == Type_ArgumentsObject &&
+ return m->d()->vtable()->type == Type_ArgumentsObject &&
!static_cast<ArgumentsObject *>(m)->context()->strictMode;
}
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 dc65b5d21a..23c9695cf4 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..da91db6aae 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,
@@ -90,6 +91,13 @@ const ArrayVTable SparseArrayData::static_vtbl =
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData));
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
+static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value)
+{
+ Value v = Value::fromReturnedValue(*target);
+ v.setValue(value);
+ *target = v.asReturnedValue();
+}
+
void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAttributes)
{
Scope scope(o->engine());
@@ -165,7 +173,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
Heap::SparseArrayData *sparse = static_cast<Heap::SparseArrayData *>(newData->d());
- uint *lastFree;
+ ReturnedValue *lastFree;
if (d && d->type() == Heap::ArrayData::Sparse) {
Heap::SparseArrayData *old = static_cast<Heap::SparseArrayData *>(d->d());
sparse->sparse = old->sparse;
@@ -180,20 +188,20 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
SparseArrayNode *n = sparse->sparse->insert(i);
n->value = i;
} else {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
}
}
if (toCopy < sparse->alloc) {
for (uint i = toCopy; i < sparse->alloc; ++i) {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
- *lastFree = UINT_MAX;
+ storeValue(lastFree, UINT_MAX);
}
// ### Could explicitly free the old data
}
@@ -230,7 +238,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 +252,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 +274,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 +289,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 +302,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 +326,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();
@@ -337,13 +345,10 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
Value *v = d->arrayData + idx;
if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
- v[1].tag = Value::Empty_Type;
- v[1].uint_32 = d->freeList;
- v[0].tag = Value::Empty_Type;
- v[0].uint_32 = idx + 1;
+ v[1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
+ v[0].setTagValue(Value::Empty_Type, idx + 1);
} else {
- v->tag = Value::Empty_Type;
- v->uint_32 = d->freeList;
+ v->setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
}
d->freeList = idx;
if (d->attrs)
@@ -369,35 +374,37 @@ 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;
+ ReturnedValue *last = &dd->freeList;
while (1) {
- if (*last == UINT_MAX) {
+ if (Value::fromReturnedValue(*last).value() == 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);
+ Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX);
}
- Q_ASSERT(dd->arrayData[*last].uint_32 != *last);
- if (dd->arrayData[*last].uint_32 == (*last + 1)) {
+ Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
+ if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
// found two slots in a row
- uint idx = *last;
- *last = dd->arrayData[*last + 1].uint_32;
+ uint idx = Value::fromReturnedValue(*last).uint_32();
+ Value lastV = Value::fromReturnedValue(*last);
+ lastV.setValue(dd->arrayData[lastV.value() + 1].value());
+ *last = lastV.rawValue();
dd->attrs[idx] = Attr_Accessor;
return idx;
}
- last = &dd->arrayData[*last].uint_32;
+ last = &dd->arrayData[Value::fromReturnedValue(*last).value()].rawValueRef();
}
} else {
- if (dd->freeList == UINT_MAX) {
+ if (Value::fromReturnedValue(dd->freeList).value() == 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;
+ uint idx = Value::fromReturnedValue(dd->freeList).value();
Q_ASSERT(idx != UINT_MAX);
- dd->freeList = dd->arrayData[idx].uint_32;
+ dd->freeList = dd->arrayData[idx].uint_32();
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
return idx;
@@ -418,12 +425,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 +439,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)
@@ -452,13 +459,10 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->arrayData[pidx + 1].tag = Value::Empty_Type;
- dd->arrayData[pidx + 1].uint_32 = dd->freeList;
- dd->arrayData[pidx].tag = Value::Undefined_Type;
- dd->arrayData[pidx].uint_32 = pidx + 1;
+ dd->arrayData[pidx + 1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
+ dd->arrayData[pidx].setTagValue(Value::Undefined_Type, pidx + 1);
} else {
- dd->arrayData[pidx].tag = Value::Empty_Type;
- dd->arrayData[pidx].uint_32 = dd->freeList;
+ dd->arrayData[pidx].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
}
dd->freeList = pidx;
@@ -468,28 +472,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 +501,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 +516,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 +610,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 +627,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 +741,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 +759,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 +799,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..729e657b1a 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -47,17 +47,17 @@ 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); }
+ const Data *d() const { return static_cast<const Data *>(m()); } \
+ Data *d() { return static_cast<Data *>(m()); }
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);
@@ -86,7 +86,7 @@ struct ArrayData : public Base {
PropertyAttributes *attrs;
union {
uint len;
- uint freeList;
+ ReturnedValue freeList;
};
union {
uint offset;
@@ -96,7 +96,7 @@ struct ArrayData : public Base {
bool isSparse() const { return type == Sparse; }
- const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable); }
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); }
inline ReturnedValue get(uint i) const {
return vtable()->get(this, i);
@@ -239,8 +239,8 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
V4_ARRAYDATA(SparseArrayData)
V4_NEEDS_DESTROY
- uint &freeList() { return d()->freeList; }
- uint freeList() const { return d()->freeList; }
+ ReturnedValue &freeList() { return d()->freeList; }
+ ReturnedValue freeList() const { return d()->freeList; }
SparseArray *sparse() const { return d()->sparse; }
void setSparse(SparseArray *s) { d()->sparse = s; }
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..f50c5ab017 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,85 +437,97 @@ 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);
return engine()->throwReferenceError(n);
}
-ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object **base)
+ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
{
Scope scope(this);
ScopedValue v(scope);
- *base = (Heap::Object *)0;
+ base->setM(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;
v = w->get(name, &hasProperty);
if (hasProperty) {
- *base = w->d();
+ base->setM(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->setM(qml->d());
return v->asReturnedValue();
+ }
+ break;
+ }
}
}
ScopedValue n(scope, name);
@@ -487,3 +549,14 @@ Heap::FunctionObject *ExecutionContext::getFunctionObject() const
return 0;
}
+
+
+QObject *QmlContext::qmlScope() const
+{
+ return d()->qml->scopeObject;
+}
+
+QQmlContextData *QmlContext::qmlContext() const
+{
+ return d()->qml->context;
+}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 8392dd836d..2667bbe0b2 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -38,6 +38,9 @@
QT_BEGIN_NAMESPACE
+class QQmlContextData;
+class QObject;
+
namespace QV4 {
namespace CompiledData {
@@ -45,6 +48,8 @@ struct CompilationUnit;
struct Function;
}
+struct QmlContextWrapper;
+struct Identifier;
struct CallContext;
struct CatchContext;
struct WithContext;
@@ -74,9 +79,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 +89,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 +107,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,16 +149,16 @@ 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);
void setProperty(String *name, const Value &value);
ReturnedValue getProperty(String *name);
- ReturnedValue getPropertyAndBase(String *name, Heap::Object **base);
+ ReturnedValue getPropertyAndBase(String *name, Value *base);
bool deleteProperty(String *name);
inline CallContext *asCallContext();
@@ -160,7 +170,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 {
@@ -174,7 +184,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
}
};
-struct CallContext : public ExecutionContext
+struct Q_QML_EXPORT CallContext : public ExecutionContext
{
V4_MANAGED(CallContext, ExecutionContext)
@@ -208,6 +218,14 @@ struct WithContext : public ExecutionContext
V4_MANAGED(WithContext, ExecutionContext)
};
+struct QmlContext : public ExecutionContext
+{
+ V4_MANAGED(QmlContext, ExecutionContext)
+
+ QObject *qmlScope() const;
+ QQmlContextData *qmlContext() const;
+};
+
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..7a6413e820 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..6efc3793ce 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -38,69 +38,73 @@
#include "qv4instr_moth_p.h"
#include "qv4runtime_p.h"
#include "qv4script_p.h"
-#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
-#include <iostream>
+#include "qv4string_p.h"
+#include "qv4objectiterator_p.h"
+#include <iostream>
#include <algorithm>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonValue>
+
+QT_BEGIN_NAMESPACE
+
using namespace QV4;
using namespace QV4::Debugging;
-namespace {
-class JavaScriptJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- int frameNr;
- const QString &script;
+Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr,
+ const QString &script)
+ : engine(engine)
+ , frameNr(frameNr)
+ , script(script)
+ , resultIsException(false)
+{}
-public:
- JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script)
- : engine(engine)
- , frameNr(frameNr)
- , script(script)
- {}
-
- void run()
- {
- Scope scope(engine);
+void Debugger::JavaScriptJob::run()
+{
+ Scope scope(engine);
- ExecutionContextSaver saver(scope, engine->currentContext());
+ ExecutionContextSaver saver(scope, engine->currentContext());
- if (frameNr > 0) {
- Value *savedContexts = scope.alloc(frameNr);
- for (int i = 0; i < frameNr; ++i) {
- savedContexts[i] = engine->currentContext();
- engine->popContext();
- }
+ if (frameNr > 0) {
+ Value *savedContexts = scope.alloc(frameNr);
+ for (int i = 0; i < frameNr; ++i) {
+ savedContexts[i] = engine->currentContext();
+ engine->popContext();
}
+ }
- ScopedContext ctx(scope, engine->currentContext());
- QV4::Script script(ctx, this->script);
- script.strictMode = ctx->d()->strictMode;
- // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
- // is a side-effect of inheritContext.
- script.inheritContext = true;
- script.parse();
- QV4::ScopedValue result(scope);
- if (!scope.engine->hasException)
- result = script.run();
- if (scope.engine->hasException)
- result = scope.engine->catchException();
- handleResult(result);
+ ScopedContext ctx(scope, engine->currentContext());
+ QV4::Script script(ctx, this->script);
+ script.strictMode = ctx->d()->strictMode;
+ // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
+ // is a side-effect of inheritContext.
+ script.inheritContext = true;
+ script.parse();
+ QV4::ScopedValue result(scope);
+ if (!scope.engine->hasException)
+ result = script.run();
+ if (scope.engine->hasException) {
+ result = scope.engine->catchException();
+ resultIsException = true;
}
+ handleResult(result);
+}
-protected:
- virtual void handleResult(QV4::ScopedValue &result) = 0;
-};
+bool Debugger::JavaScriptJob::hasExeption() const
+{
+ return resultIsException;
+}
-class EvalJob: public JavaScriptJob
+class EvalJob: public Debugger::JavaScriptJob
{
bool result;
public:
EvalJob(QV4::ExecutionEngine *engine, const QString &script)
- : JavaScriptJob(engine, /*frameNr*/-1, script)
+ : Debugger::JavaScriptJob(engine, /*frameNr*/-1, script)
, result(false)
{}
@@ -115,58 +119,8 @@ public:
}
};
-class ExpressionEvalJob: public JavaScriptJob
-{
- Debugger::Collector *collector;
-
-public:
- ExpressionEvalJob(ExecutionEngine *engine, int frameNr, const QString &expression, Debugger::Collector *collector)
- : JavaScriptJob(engine, frameNr, expression)
- , collector(collector)
- {
- }
-
- virtual void handleResult(QV4::ScopedValue &result)
- {
- collector->collect(QStringLiteral("body"), result);
- }
-};
-
-class GatherSourcesJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- const int seq;
-
-public:
- GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
- : engine(engine)
- , seq(seq)
- {}
-
- ~GatherSourcesJob() {}
-
- void run()
- {
- QStringList sources;
-
- foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
- QString fileName = unit->fileName();
- if (!fileName.isEmpty())
- sources.append(fileName);
- }
-
- Debugger *debugger = engine->debugger;
- QMetaObject::invokeMethod(debugger->agent(), "sourcesCollected", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, debugger),
- Q_ARG(QStringList, sources),
- Q_ARG(int, seq));
- }
-};
-}
-
Debugger::Debugger(QV4::ExecutionEngine *engine)
: m_engine(engine)
- , m_agent(0)
, m_state(Running)
, m_stepping(NotStepping)
, m_pauseRequested(false)
@@ -180,41 +134,6 @@ Debugger::Debugger(QV4::ExecutionEngine *engine)
qMetaTypeId<PauseReason>();
}
-Debugger::~Debugger()
-{
- detachFromAgent();
-}
-
-void Debugger::attachToAgent(DebuggerAgent *agent)
-{
- Q_ASSERT(!m_agent);
- m_agent = agent;
-}
-
-void Debugger::detachFromAgent()
-{
- DebuggerAgent *agent = 0;
- {
- QMutexLocker locker(&m_lock);
- agent = m_agent;
- m_agent = 0;
- }
- if (agent)
- agent->removeDebugger(this);
-}
-
-void Debugger::gatherSources(int requestSequenceNr)
-{
- QMutexLocker locker(&m_lock);
-
- m_gatherSources = new GatherSourcesJob(m_engine, requestSequenceNr);
- if (m_state == Paused) {
- runInEngine_havingLock(m_gatherSources);
- delete m_gatherSources;
- m_gatherSources = 0;
- }
-}
-
void Debugger::pause()
{
QMutexLocker locker(&m_lock);
@@ -272,251 +191,6 @@ QVector<StackFrame> Debugger::stackTrace(int frameLimit) const
return m_engine->stackTrace(frameLimit);
}
-static inline Heap::CallContext *findContext(Heap::ExecutionContext *ctxt, int frame)
-{
- if (!ctxt)
- return 0;
-
- Scope scope(ctxt->engine);
- ScopedContext ctx(scope, ctxt);
- while (ctx) {
- CallContext *cCtxt = ctx->asCallContext();
- if (cCtxt && cCtxt->d()->function) {
- if (frame < 1)
- return cCtxt->d();
- --frame;
- }
- ctx = ctx->d()->parent;
- }
-
- return 0;
-}
-
-static inline Heap::CallContext *findScope(Heap::ExecutionContext *ctxt, int scope)
-{
- if (!ctxt)
- return 0;
-
- Scope s(ctxt->engine);
- ScopedContext ctx(s, ctxt);
- for (; scope > 0 && ctx; --scope)
- ctx = ctx->d()->outer;
-
- return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
-}
-
-void Debugger::collectArgumentsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class ArgumentCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- ArgumentCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- ~ArgumentCollectJob() {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- int nFormals = ctxt->formalCount();
- for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->formals()[nFormals - i - 1])
- qName = name->string;
- v = ctxt->argument(i);
- collector->collect(qName, v);
- }
- }
- };
-
- ArgumentCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-/// Same as \c retrieveArgumentsFromContext, but now for locals.
-void Debugger::collectLocalsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class LocalCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- LocalCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->variables()[i])
- qName = name->string;
- v = ctxt->d()->locals[i];
- collector->collect(qName, v);
- }
- }
- };
-
- LocalCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame)
-{
- if (state() != Paused)
- return false;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- bool *foundThis;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, bool *foundThis)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , foundThis(foundThis)
- {}
-
- void run()
- {
- *foundThis = myRun();
- }
-
- bool myRun()
- {
- Scope scope(engine);
- ScopedContext ctxt(scope, findContext(engine->currentContext(), frameNr));
- while (ctxt) {
- if (CallContext *cCtxt = ctxt->asCallContext())
- if (cCtxt->d()->activation)
- break;
- ctxt = ctxt->d()->outer;
- }
-
- if (!ctxt)
- return false;
-
- ScopedObject o(scope, ctxt->asCallContext()->d()->activation);
- collector->collect(o);
- return true;
- }
- };
-
- bool foundThis = false;
- ThisCollectJob job(m_engine, collector, frame, &foundThis);
- runInEngine(&job);
- return foundThis;
-}
-
-void Debugger::collectThrownValue(Collector *collector)
-{
- if (state() != Paused || !m_engine->hasException)
- return;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector)
- : engine(engine)
- , collector(collector)
- {}
-
- void run()
- {
- Scope scope(engine);
- ScopedValue v(scope, engine->exceptionValue);
- collector->collect(QStringLiteral("exception"), v);
- }
- };
-
- ThisCollectJob job(m_engine, collector);
- runInEngine(&job);
-}
-
-void Debugger::collectReturnedValue(Collector *collector) const
-{
- if (state() != Paused)
- return;
-
- Scope scope(m_engine);
- ScopedObject o(scope, m_returnedValue.valueRef());
- collector->collect(o);
-}
-
-QVector<Heap::ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
-{
- QVector<Heap::ExecutionContext::ContextType> types;
-
- if (state() != Paused)
- return types;
-
- Scope scope(m_engine);
- Scoped<CallContext> sctxt(scope, findContext(m_engine->currentContext(), frame));
- if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_SimpleCallContext)
- return types;
-
- ScopedContext it(scope, sctxt->d());
- for (; it; it = it->d()->outer)
- types.append(it->d()->type);
-
- return types;
-}
-
-
-void Debugger::evaluateExpression(int frameNr, const QString &expression, Debugger::Collector *resultsCollector)
-{
- Q_ASSERT(state() == Paused);
-
- Q_ASSERT(m_runningJob == 0);
- ExpressionEvalJob job(m_engine, frameNr, expression, resultsCollector);
- runInEngine(&job);
-}
-
void Debugger::maybeBreakAtInstruction()
{
if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
@@ -610,9 +284,7 @@ void Debugger::pauseAndWait(PauseReason reason)
return;
m_state = Paused;
- QMetaObject::invokeMethod(m_agent, "debuggerPaused", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, this),
- Q_ARG(QV4::Debugging::PauseReason, reason));
+ emit debuggerPaused(this, reason);
while (true) {
m_runningCondition.wait(&m_lock);
@@ -662,174 +334,8 @@ void Debugger::runInEngine_havingLock(Debugger::Job *job)
m_runningJob = 0;
}
-void DebuggerAgent::addDebugger(Debugger *debugger)
-{
- Q_ASSERT(!m_debuggers.contains(debugger));
- m_debuggers << debugger;
- debugger->attachToAgent(this);
-
- debugger->setBreakOnThrow(m_breakOnThrow);
-
- foreach (const BreakPoint &breakPoint, m_breakPoints.values())
- if (breakPoint.enabled)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
-}
-
-void DebuggerAgent::removeDebugger(Debugger *debugger)
-{
- m_debuggers.removeAll(debugger);
- debugger->detachFromAgent();
-}
-
-void DebuggerAgent::pause(Debugger *debugger) const
-{
- debugger->pause();
-}
-
-void DebuggerAgent::pauseAll() const
-{
- foreach (Debugger *debugger, m_debuggers)
- pause(debugger);
-}
-
-void DebuggerAgent::resumeAll() const
-{
- foreach (Debugger *debugger, m_debuggers)
- if (debugger->state() == Debugger::Paused)
- debugger->resume(Debugger::FullThrottle);
-}
-
-int DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
-{
- if (enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->addBreakPoint(fileName, lineNumber, condition);
-
- int id = m_breakPoints.size();
- m_breakPoints.insert(id, BreakPoint(fileName, lineNumber, enabled, condition));
- return id;
-}
-
-void DebuggerAgent::removeBreakPoint(int id)
-{
- BreakPoint breakPoint = m_breakPoints.value(id);
- if (!breakPoint.isValid())
- return;
-
- m_breakPoints.remove(id);
-
- if (breakPoint.enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
-}
-
-void DebuggerAgent::removeAllBreakPoints()
-{
- QList<int> ids = m_breakPoints.keys();
- foreach (int id, ids)
- removeBreakPoint(id);
-}
-
-void DebuggerAgent::enableBreakPoint(int id, bool onoff)
-{
- BreakPoint &breakPoint = m_breakPoints[id];
- if (!breakPoint.isValid() || breakPoint.enabled == onoff)
- return;
- breakPoint.enabled = onoff;
-
- foreach (Debugger *debugger, m_debuggers) {
- if (onoff)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
- else
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
- }
-}
-
-QList<int> DebuggerAgent::breakPointIds(const QString &fileName, int lineNumber) const
-{
- QList<int> ids;
-
- for (QHash<int, BreakPoint>::const_iterator i = m_breakPoints.begin(), ei = m_breakPoints.end(); i != ei; ++i)
- if (i->lineNr == lineNumber && fileName.endsWith(i->fileName))
- ids.push_back(i.key());
-
- return ids;
-}
-
-void DebuggerAgent::setBreakOnThrow(bool onoff)
-{
- if (onoff != m_breakOnThrow) {
- m_breakOnThrow = onoff;
- foreach (Debugger *debugger, m_debuggers)
- debugger->setBreakOnThrow(onoff);
- }
-}
-
-DebuggerAgent::~DebuggerAgent()
-{
- foreach (Debugger *debugger, m_debuggers)
- debugger->detachFromAgent();
-
- Q_ASSERT(m_debuggers.isEmpty());
-}
-
-Debugger::Collector::~Collector()
-{
-}
-
-void Debugger::Collector::collect(const QString &name, const ScopedValue &value)
-{
- switch (value->type()) {
- case Value::Empty_Type:
- Q_ASSERT(!"empty Value encountered");
- break;
- case Value::Undefined_Type:
- addUndefined(name);
- break;
- case Value::Null_Type:
- addNull(name);
- break;
- case Value::Boolean_Type:
- addBoolean(name, value->booleanValue());
- break;
- case Value::Managed_Type:
- if (String *s = value->asString())
- addString(name, s->toQString());
- else
- addObject(name, value);
- break;
- case Value::Integer_Type:
- addInteger(name, value->int_32);
- break;
- default: // double
- addDouble(name, value->doubleValue());
- break;
- }
-}
-
-void Debugger::Collector::collect(Object *object)
-{
- bool property = true;
- qSwap(property, m_isProperty);
-
- Scope scope(m_engine);
- ObjectIterator it(scope, object, ObjectIterator::EnumerableOnly);
- ScopedValue name(scope);
- ScopedValue value(scope);
- while (true) {
- Value v;
- name = it.nextPropertyNameAsString(&v);
- if (name->isNull())
- break;
- QString key = name->toQStringNoThrow();
- value = v;
- collect(key, value);
- }
-
- qSwap(property, m_isProperty);
-}
-
-
Debugger::Job::~Job()
{
}
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index e6a9750351..86faba45f7 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -44,6 +44,8 @@
#include <QMutex>
#include <QWaitCondition>
+#include <QtCore/QJsonObject>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -59,8 +61,6 @@ enum PauseReason {
Step
};
-class DebuggerAgent;
-
struct DebuggerBreakPoint {
DebuggerBreakPoint(const QString &fileName, int line)
: fileName(fileName), lineNumber(line)
@@ -79,43 +79,31 @@ inline bool operator==(const DebuggerBreakPoint &a, const DebuggerBreakPoint &b)
typedef QHash<DebuggerBreakPoint, QString> BreakPoints;
-
-class Q_QML_EXPORT Debugger
+class Q_QML_EXPORT Debugger : public QObject
{
+ Q_OBJECT
public:
- class Job
+ class Q_QML_EXPORT Job
{
public:
virtual ~Job() = 0;
virtual void run() = 0;
};
- class Q_QML_EXPORT Collector
+ class Q_QML_EXPORT JavaScriptJob: public Job
{
- public:
- Collector(ExecutionEngine *engine): m_engine(engine), m_isProperty(false) {}
- virtual ~Collector();
+ QV4::ExecutionEngine *engine;
+ int frameNr;
+ const QString &script;
+ bool resultIsException;
- void collect(const QString &name, const ScopedValue &value);
- void collect(Object *object);
+ public:
+ JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script);
+ void run();
+ bool hasExeption() const;
protected:
- virtual void addUndefined(const QString &name) = 0;
- virtual void addNull(const QString &name) = 0;
- virtual void addBoolean(const QString &name, bool value) = 0;
- virtual void addString(const QString &name, const QString &value) = 0;
- virtual void addObject(const QString &name, const Value &value) = 0;
- virtual void addInteger(const QString &name, int value) = 0;
- virtual void addDouble(const QString &name, double value) = 0;
-
- QV4::ExecutionEngine *engine() const { return m_engine; }
-
- bool isProperty() const { return m_isProperty; }
- void setIsProperty(bool onoff) { m_isProperty = onoff; }
-
- private:
- QV4::ExecutionEngine *m_engine;
- bool m_isProperty;
+ virtual void handleResult(QV4::ScopedValue &result) = 0;
};
enum State {
@@ -133,16 +121,10 @@ public:
};
Debugger(ExecutionEngine *engine);
- ~Debugger();
ExecutionEngine *engine() const
{ return m_engine; }
- void attachToAgent(DebuggerAgent *agent);
- void detachFromAgent();
- DebuggerAgent *agent() const { return m_agent; }
-
- void gatherSources(int requestSequenceNr);
void pause();
void resume(Speed speed);
@@ -166,14 +148,10 @@ public:
}
QVector<StackFrame> stackTrace(int frameLimit = -1) const;
- void collectArgumentsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- void collectLocalsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- bool collectThisInContext(Collector *collector, int frame = 0);
- void collectThrownValue(Collector *collector);
- void collectReturnedValue(Collector *collector) const;
QVector<Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
- void evaluateExpression(int frameNr, const QString &expression, Collector *resultsCollector);
+ Function *getFunction() const;
+ void runInEngine(Job *job);
public: // compile-time interface
void maybeBreakAtInstruction();
@@ -183,21 +161,19 @@ public: // execution hooks
void leavingFunction(const ReturnedValue &retVal);
void aboutToThrow();
-private:
- Function *getFunction() const;
+signals:
+ void sourcesCollected(QV4::Debugging::Debugger *self, const QStringList &sources, int seq);
+ void debuggerPaused(QV4::Debugging::Debugger *self, QV4::Debugging::PauseReason reason);
+private:
// requires lock to be held
void pauseAndWait(PauseReason reason);
-
bool reallyHitTheBreakPoint(const QString &filename, int linenr);
-
- void runInEngine(Job *job);
void runInEngine_havingLock(Debugger::Job *job);
private:
QV4::ExecutionEngine *m_engine;
QV4::PersistentValue m_currentContext;
- DebuggerAgent *m_agent;
QMutex m_lock;
QWaitCondition m_runningCondition;
State m_state;
@@ -214,54 +190,6 @@ private:
QWaitCondition m_jobIsRunning;
};
-class Q_QML_EXPORT DebuggerAgent : public QObject
-{
- Q_OBJECT
-public:
- DebuggerAgent(): m_breakOnThrow(false) {}
- ~DebuggerAgent();
-
- void addDebugger(Debugger *debugger);
- void removeDebugger(Debugger *debugger);
-
- void pause(Debugger *debugger) const;
- void pauseAll() const;
- void resumeAll() const;
- int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString());
- void removeBreakPoint(int id);
- void removeAllBreakPoints();
- void enableBreakPoint(int id, bool onoff);
- QList<int> breakPointIds(const QString &fileName, int lineNumber) const;
-
- bool breakOnThrow() const { return m_breakOnThrow; }
- void setBreakOnThrow(bool onoff);
-
- Q_INVOKABLE virtual void debuggerPaused(QV4::Debugging::Debugger *debugger,
- QV4::Debugging::PauseReason reason) = 0;
- Q_INVOKABLE virtual void sourcesCollected(QV4::Debugging::Debugger *debugger,
- QStringList sources, int requestSequenceNr) = 0;
-
-protected:
- QList<Debugger *> m_debuggers;
-
- struct BreakPoint {
- QString fileName;
- int lineNr;
- bool enabled;
- QString condition;
-
- BreakPoint(): lineNr(-1), enabled(false) {}
- BreakPoint(const QString &fileName, int lineNr, bool enabled, const QString &condition)
- : fileName(fileName), lineNr(lineNr), enabled(enabled), condition(condition)
- {}
-
- bool isValid() const { return lineNr >= 0 && !fileName.isEmpty(); }
- };
-
- QHash<int, BreakPoint> m_breakPoints;
- bool m_breakOnThrow;
-};
-
} // namespace Debugging
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index e1282eeca9..caf07e8b0b 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"
@@ -197,6 +196,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)
@@ -211,13 +211,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
@@ -241,6 +237,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
@@ -251,208 +254,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()
@@ -471,7 +474,6 @@ ExecutionEngine::~ExecutionEngine()
foreach (QV4::CompiledData::CompilationUnit *unit, remainingUnits)
unit->unlink();
- delete m_qmlExtensions;
emptyClass->destroy();
delete classPool;
delete bumperPointerAllocator;
@@ -504,10 +506,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)
@@ -519,7 +521,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();
@@ -551,10 +553,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();
}
@@ -653,7 +655,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();
}
@@ -723,7 +725,7 @@ Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
return obj->d();
}
-Heap::Object *ExecutionEngine::qmlContextObject() const
+Heap::QmlContext *ExecutionEngine::qmlContext() const
{
Heap::ExecutionContext *ctx = currentContext();
@@ -740,8 +742,49 @@ 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;
+ return static_cast<Heap::QmlContext *>(ctx);
+}
+
+Heap::QmlContextWrapper *ExecutionEngine::qmlContextObject() const
+{
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
+ Q_ASSERT(ctx->qml);
+ return ctx->qml;
+}
+
+QObject *ExecutionEngine::qmlScopeObject() const
+{
+ return qmlContextObject()->scopeObject;
+}
+
+ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
+{
+ QQmlContextData *ctx = callingQmlContext();
+ if (!ctx->imports)
+ return Encode::undefined();
+ // Search for attached properties, enums and imported scripts
+ QQmlTypeNameCache::Result r = ctx->imports->query(name);
+
+ Q_ASSERT(r.isValid());
+ Q_ASSERT(r.type);
+ Q_ASSERT(r.type->isSingleton());
+
+ QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
+ QQmlEngine *e = qmlEngine();
+ siinfo->init(e);
+
+ if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
+ return QV4::QObjectWrapper::wrap(this, qobjectSingleton);
+ return QJSValuePrivate::convertedToValue(this, siinfo->scriptApi(e));
+}
+
+QQmlContextData *ExecutionEngine::callingQmlContext() const
+{
+ Heap::QmlContextWrapper *w = qmlContextObject();
+
+ return w ? w->context.contextData() : 0;
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -777,7 +820,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);
@@ -889,8 +932,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,98 +945,11 @@ void ExecutionEngine::markObjects()
Q_ASSERT(c->inUse());
if (!c->isMarked()) {
c->setMarkBit();
- c->gcGetVtable()->markObjects(c, this);
+ c->vtable()->markObjects(c, this);
}
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();
@@ -1003,13 +957,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
@@ -1020,7 +967,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)
@@ -1041,8 +988,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;
}
@@ -1175,7 +1122,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);
@@ -1198,7 +1145,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)
@@ -1210,10 +1157,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());
@@ -1229,7 +1176,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;
@@ -1267,11 +1214,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)!
@@ -1287,7 +1234,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);
@@ -1298,7 +1245,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();
}
@@ -1306,7 +1253,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);
@@ -1319,7 +1266,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);
@@ -1497,7 +1444,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();
}
@@ -1630,93 +1577,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;
@@ -1724,15 +1668,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;
@@ -1740,20 +1684,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;
@@ -1763,7 +1706,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);
}
@@ -1788,21 +1731,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>()) {
@@ -1812,7 +1756,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) {
@@ -1826,11 +1770,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..90564a9652 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,12 @@ public:
Heap::Object *newForEachIteratorObject(Object *o);
- Heap::Object *qmlContextObject() const;
+ Heap::QmlContext *qmlContext() const;
+ QV4::Heap::QmlContextWrapper *qmlContextObject() const;
+ QObject *qmlScopeObject() const;
+ ReturnedValue qmlSingletonWrapper(String *name);
+ QQmlContextData *callingQmlContext() const;
+
StackTrace stackTrace(int frameLimit = -1) const;
StackFrame currentStackFrame() const;
@@ -305,12 +406,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 +434,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 +472,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..a6c2a25b91 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,18 +354,18 @@ 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");
+ qname = QStringLiteral("Error");
else
qname = name->toQString();
- ScopedString s(scope, ctx->d()->engine->newString(QString::fromLatin1("message")));
+ ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("message")));
ScopedValue message(scope, o->get(s));
QString qmessage;
if (!message->isUndefined())
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 071f5b8c9a..e0fbcb4d8d 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 be63b31e1e..98a4490211 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..6412e65fa9 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"
@@ -46,7 +46,7 @@
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
-#include <private/qqmlcontextwrapper_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qqmlengine_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_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();
}
@@ -209,12 +208,12 @@ Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *sco
bool FunctionObject::isBinding() const
{
- return d()->vtable == QQmlBindingFunction::staticVTable();
+ return d()->vtable() == QQmlBindingFunction::staticVTable();
}
bool FunctionObject::isBoundFunction() const
{
- return d()->vtable == BoundFunction::staticVTable();
+ return d()->vtable() == BoundFunction::staticVTable();
}
QQmlSourceLocation FunctionObject::sourceLocation() const
@@ -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());
@@ -431,7 +430,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
if (v4->hasException)
return Encode::undefined();
@@ -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);
+ QQmlPropertyCapture::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());
@@ -514,7 +513,10 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#ifndef QT_NO_DEBUG
+ ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -529,27 +531,30 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
ScopedObject result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
if (!result)
return callData->thisObject.asReturnedValue();
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());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#ifndef QT_NO_DEBUG
+ ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -564,7 +569,7 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
return result->asReturnedValue();
}
@@ -575,7 +580,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 +593,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();
@@ -605,7 +610,10 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#ifndef QT_NO_DEBUG
+ ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
Q_ASSERT(v4->currentContext() == &ctx);
@@ -614,9 +622,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();
@@ -626,7 +634,10 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#ifndef QT_NO_DEBUG
+ ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
Q_ASSERT(v4->currentContext() == &ctx);
@@ -650,24 +661,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 +696,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..2c6a195746 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..759c6795e2 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 {
@@ -277,8 +278,6 @@ struct PropertyAttributes
setConfigurable(!(f & Attr_NotConfigurable));
}
}
- PropertyAttributes(const PropertyAttributes &other) : m_all(other.m_all) {}
- PropertyAttributes & operator=(const PropertyAttributes &other) { m_all = other.m_all; return *this; }
void setType(Type t) { m_type = t; type_set = true; }
Type type() const { return type_set ? (Type)m_type : Generic; }
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 8e33cec57f..ec7b9b3f7d 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -32,13 +32,15 @@
****************************************************************************/
#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 "qv4profiling_p.h"
#include "qv4script_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -47,6 +49,7 @@
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
+#include "private/qtools_p.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
@@ -56,25 +59,8 @@
#include <wtf/MathExtras.h>
using namespace QV4;
-
-
-static inline char toHex(char c)
-{
- static const char hexnumbers[] = "0123456789ABCDEF";
- return hexnumbers[c & 0xf];
-}
-
-static int fromHex(QChar ch)
-{
- ushort c = ch.unicode();
- if ((c >= '0') && (c <= '9'))
- return c - '0';
- if ((c >= 'A') && (c <= 'F'))
- return c - 'A' + 10;
- if ((c >= 'a') && (c <= 'f'))
- return c - 'a' + 10;
- return -1;
-}
+using QtMiscUtils::toHexUpper;
+using QtMiscUtils::fromHex;
static QString escape(const QString &input)
{
@@ -93,16 +79,16 @@ static QString escape(const QString &input)
output.append(QChar(uc));
} else {
output.append('%');
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
} else {
output.append('%');
output.append('u');
- output.append(QLatin1Char(toHex(uc >> 12)));
- output.append(QLatin1Char(toHex(uc >> 8)));
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 12)));
+ output.append(QLatin1Char(toHexUpper(uc >> 8)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
}
return output;
@@ -119,10 +105,10 @@ static QString unescape(const QString &input)
if ((c == '%') && (i + 1 < length)) {
QChar a = input.at(i);
if ((a == 'u') && (i + 4 < length)) {
- int d3 = fromHex(input.at(i+1));
- int d2 = fromHex(input.at(i+2));
- int d1 = fromHex(input.at(i+3));
- int d0 = fromHex(input.at(i+4));
+ int d3 = fromHex(input.at(i+1).unicode());
+ int d2 = fromHex(input.at(i+2).unicode());
+ int d1 = fromHex(input.at(i+3).unicode());
+ int d0 = fromHex(input.at(i+4).unicode());
if ((d3 != -1) && (d2 != -1) && (d1 != -1) && (d0 != -1)) {
ushort uc = ushort((d3 << 12) | (d2 << 8) | (d1 << 4) | d0);
result.append(QChar(uc));
@@ -131,8 +117,8 @@ static QString unescape(const QString &input)
result.append(c);
}
} else {
- int d1 = fromHex(a);
- int d0 = fromHex(input.at(i+1));
+ int d1 = fromHex(a.unicode());
+ int d0 = fromHex(input.at(i+1).unicode());
if ((d1 != -1) && (d0 != -1)) {
c = (d1 << 4) | d0;
i += 2;
@@ -153,8 +139,8 @@ static const char uriUnescapedReserved[] = "-_.!~*'();/?:@&=+$,#";
static void addEscapeSequence(QString &output, uchar ch)
{
output.append(QLatin1Char('%'));
- output.append(QLatin1Char(toHex(ch >> 4)));
- output.append(QLatin1Char(toHex(ch & 0xf)));
+ output.append(QLatin1Char(toHexUpper(ch >> 4)));
+ output.append(QLatin1Char(toHexUpper(ch & 0xf)));
}
static QString encode(const QString &input, const char *unescapedSet, bool *ok)
@@ -246,8 +232,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (i + 2 >= length)
goto error;
- int d1 = fromHex(input.at(i+1));
- int d0 = fromHex(input.at(i+2));
+ int d1 = fromHex(input.at(i+1).unicode());
+ int d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -281,8 +267,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (input.at(i) != percent)
goto error;
- d1 = fromHex(input.at(i+1));
- d0 = fromHex(input.at(i+2));
+ d1 = fromHex(input.at(i+1).unicode());
+ d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -339,14 +325,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();
@@ -395,14 +381,14 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
ctx->d()->strictMode = false;
ctx->d()->compilationUnit = function->compilationUnit;
- return function->code(ctx->engine(), function->codeData);
+ return Q_V4_PROFILE(ctx->engine(), function);
}
-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/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index ff374225f4..58f808b4d5 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -80,8 +80,8 @@ public:
if (!entry || entry->isMarked())
continue;
entry->setMarkBit();
- Q_ASSERT(entry->gcGetVtable()->markObjects);
- entry->gcGetVtable()->markObjects(entry, e);
+ Q_ASSERT(entry->vtable()->markObjects);
+ entry->vtable()->markObjects(entry, e);
}
}
};
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..f703e85399 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->setM(0);
+ } else {
+ for (uint j = 0; j <i; ++j) {
+ if (stringify.propertyList[j].m() == v->m()) {
+ v->setM(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..bb7ee43b4e 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,
@@ -59,7 +59,7 @@ const ManagedVTable Managed::static_vtbl =
QString Managed::className() const
{
const char *s = 0;
- switch (Type(d()->vtable->type)) {
+ switch (Type(d()->vtable()->type)) {
case Type_Invalid:
case Type_String:
return QString();
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 0fe5c7ee49..6f5564300f 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,10 +65,10 @@ 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); }
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
#define Q_MANAGED_TYPE(type) \
public: \
@@ -78,31 +78,6 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
(classname::func == QV4::Managed::func ? 0 : classname::func)
-struct GCDeletable
-{
- GCDeletable() : next(0), lastCall(false) {}
- virtual ~GCDeletable() {}
- GCDeletable *next;
- 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 +96,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 +116,6 @@ private:
public:
- inline void mark(QV4::ExecutionEngine *engine);
-
enum Type {
Type_Invalid,
Type_String,
@@ -167,55 +140,15 @@ 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; }
- bool isStringObject() const { return d()->vtable->type == Type_StringObject; }
+ bool isListType() const { return d()->vtable()->type == Type_QmlSequence; }
+
+ bool isArrayObject() const { return d()->vtable()->type == Type_ArrayObject; }
+ bool isStringObject() const { return d()->vtable()->type == Type_StringObject; }
QString className() const;
bool isEqualTo(const Managed *other) const
- { return d()->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
+ { return d()->vtable()->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
static bool isEqualTo(Managed *m, Managed *other);
@@ -231,37 +164,15 @@ private:
template<>
-inline Managed *value_cast(const Value &v) {
- return v.asManaged();
+inline const Managed *Value::as() const {
+ if (isManaged())
+ return managed();
+ return 0;
}
-template<typename T>
-inline T *managed_cast(Managed *m)
-{
- return m ? m->as<T>() : 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 4a1a94e872..4ae30a7f35 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()));
@@ -81,9 +82,9 @@ QT_WARNING_DISABLE_INTEL(239)
QT_WARNING_POP
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);
@@ -93,7 +94,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());
@@ -103,7 +104,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();
@@ -119,7 +120,7 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
if (ctx->argc() && !ctx->args()[0].isUndefined()) {
int radix = ctx->args()[0].toInt32();
if (radix < 2 || radix > 36)
- return ctx->engine()->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
+ return ctx->engine()->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
if (std::isnan(num)) {
@@ -197,7 +198,7 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
QString str;
if (std::isnan(v))
- str = QString::fromLatin1("NaN");
+ str = QStringLiteral("NaN");
else if (qIsInf(v))
str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity");
else if (v < 1.e21) {
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..b3c0863e3e 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 (o->vtable()->type == Type_StringObject) {
+ 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()) {
@@ -516,10 +514,10 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->setter = Lookup::setterGeneric;
}
-void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
- *name = 0;
+ name->setM(0);
*index = UINT_MAX;
if (o->arrayData()) {
@@ -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;
@@ -574,7 +572,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- *name = o->engine()->newString(n->string);
+ name->setM(o->engine()->newString(n->string));
*attrs = a;
pd->copy(p, a);
return;
@@ -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;
@@ -1029,9 +1028,9 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
} else { // clause 10
Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
if (!cattrs.isConfigurable()) {
- if (!p->value.isEmpty() && current->value.val != p->value.val)
+ if (!p->value.isEmpty() && current->value.rawValue() != p->value.rawValue())
goto reject;
- if (!p->set.isEmpty() && current->set.val != p->set.val)
+ if (!p->set.isEmpty() && current->set.rawValue() != p->set.rawValue())
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..f129312819 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,9 +66,9 @@ 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); }
+ Data *d() const { return static_cast<Data *>(m()); }
#define V4_OBJECT2(DataClass, superClass) \
public: \
@@ -77,33 +76,33 @@ 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); }
+ 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);
+ void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
#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, \
@@ -141,15 +140,15 @@ struct Q_QML_EXPORT Object: Managed {
const Property *propertyAt(uint index) const { return d()->propertyAt(index); }
Property *propertyAt(uint index) { return d()->propertyAt(index); }
- const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable); }
+ const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
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,38 +287,38 @@ 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); }
- void advanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+ void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{ 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 void advanceIterator(Managed *m, ObjectIterator *it, Value *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..585f9f5c2e 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,14 +63,14 @@ 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;
+ object->setM(o ? o->m() : 0);
+ current->setM(o ? o->m() : 0);
#if QT_POINTER_SIZE == 4
- object->tag = QV4::Value::Managed_Type;
- current->tag = QV4::Value::Managed_Type;
+ object->setTag(QV4::Value::Managed_Type);
+ current->setTag(QV4::Value::Managed_Type);
#endif
if (object->as<ArgumentsObject>()) {
@@ -78,12 +79,12 @@ void ObjectIterator::init(Object *o)
}
}
-void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
- *name = 0;
+ name->setM(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;
@@ -119,9 +120,9 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
}
if (flags & WithProtoChain)
- current->m = current->objectValue()->prototype();
+ current->setM(current->objectValue()->prototype());
else
- current->m = (Heap::Base *)0;
+ current->setM(0);
arrayIndex = 0;
memberIndex = 0;
@@ -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..bfe04b33aa 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -57,9 +57,9 @@ 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);
- void next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
+ ObjectIterator(Scope &scope, const Object *o, uint flags);
+ void init(const Object *o);
+ void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(Value *value);
ReturnedValue nextPropertyNameAsString(Value *value);
ReturnedValue nextPropertyNameAsString();
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 9356ea434e..1edf76e2de 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();
@@ -390,7 +392,7 @@ ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
} else {
ScopedObject obj(scope, RuntimeHelpers::toObject(scope.engine, ctx->thisObject()));
QString className = obj->className();
- return ctx->d()->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue();
+ return ctx->d()->engine->newString(QStringLiteral("[object %1]").arg(className))->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..4ec7103644 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"
@@ -78,11 +78,11 @@ Page *allocatePage(PersistentValueStorage *storage)
if (p->header.next)
p->header.next->header.prev = &p->header.next;
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
- p->values[i].tag = QV4::Value::Empty_Type;
- p->values[i].int_32 = i + 1;
+ p->values[i].setTag(QV4::Value::Empty_Type);
+ p->values[i].setInt_32(i + 1);
}
- p->values[kEntriesPerPage - 1].tag = QV4::Value::Empty_Type;
- p->values[kEntriesPerPage - 1].int_32 = -1;
+ p->values[kEntriesPerPage - 1].setTag(QV4::Value::Empty_Type);
+ p->values[kEntriesPerPage - 1].setInt_32(-1);
storage->firstPage = p;
@@ -97,7 +97,7 @@ PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++()
while (p) {
while (index < kEntriesPerPage - 1) {
++index;
- if (static_cast<Page *>(p)->values[index].tag != QV4::Value::Empty_Type)
+ if (static_cast<Page *>(p)->values[index].tag() != QV4::Value::Empty_Type)
return *this;
}
index = -1;
@@ -147,10 +147,10 @@ Value *PersistentValueStorage::allocate()
p = allocatePage(this);
Value *v = p->values + p->header.freeList;
- p->header.freeList = v->int_32;
+ p->header.freeList = v->int_32();
++p->header.refCount;
- v->val = Encode::undefined();
+ v->setRawValue(Encode::undefined());
return v;
}
@@ -162,8 +162,8 @@ void PersistentValueStorage::free(Value *v)
Page *p = getPage(v);
- v->tag = QV4::Value::Empty_Type;
- v->int_32 = p->header.freeList;
+ v->setTag(QV4::Value::Empty_Type);
+ v->setInt_32(p->header.freeList);
p->header.freeList = v - p->values;
if (!--p->header.refCount) {
if (p->header.prev)
@@ -178,8 +178,8 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
+ Q_ASSERT (h->vtable()->markObjects);
+ h->vtable()->markObjects(h, engine);
}
}
@@ -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..9b77599904 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
@@ -55,10 +56,10 @@ FunctionCallProperties FunctionCall::resolve() const
Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine)
{
- static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >();
- static int metatype2 = qRegisterMetaType<QList<QV4::Profiling::MemoryAllocationProperties> >();
- Q_UNUSED(metatype);
- Q_UNUSED(metatype2);
+ static int meta = qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >();
+ static int meta2 = qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >();
+ Q_UNUSED(meta);
+ Q_UNUSED(meta2);
m_timer.start();
}
@@ -75,7 +76,7 @@ void Profiler::stopProfiling()
void Profiler::reportData()
{
- QList<FunctionCallProperties> resolved;
+ QVector<FunctionCallProperties> resolved;
resolved.reserve(m_data.size());
FunctionCallComparator comp;
foreach (const FunctionCall &call, m_data) {
@@ -83,14 +84,13 @@ void Profiler::reportData()
resolved.insert(std::upper_bound(resolved.begin(), resolved.end(), props, comp), props);
}
emit dataReady(resolved, m_memory_data);
+ m_data.clear();
+ m_memory_data.clear();
}
void Profiler::startProfiling(quint64 features)
{
if (featuresEnabled == 0) {
- m_data.clear();
- m_memory_data.clear();
-
if (features & (1 << FeatureMemoryAllocation)) {
qint64 timestamp = m_timer.nsecsElapsed();
MemoryAllocationProperties heap = {timestamp,
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index c3441eaacd..cc00af0193 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -155,14 +155,14 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &,
- const QList<QV4::Profiling::MemoryAllocationProperties> &);
+ void dataReady(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private:
QV4::ExecutionEngine *m_engine;
QElapsedTimer m_timer;
QVector<FunctionCall> m_data;
- QList<MemoryAllocationProperties> m_memory_data;
+ QVector<MemoryAllocationProperties> m_memory_data;
friend class FunctionCallProfiler;
};
@@ -202,7 +202,7 @@ Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QList<QV4::Profiling::FunctionCallProperties>)
-Q_DECLARE_METATYPE(QList<QV4::Profiling::MemoryAllocationProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
#endif // QV4PROFILING_H
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 1b55abd1f7..db8c6017e1 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,12 +84,12 @@ 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);
- set.m = reinterpret_cast<Heap::Base *>(setter);
+ value.setM(reinterpret_cast<Heap::Base *>(getter));
+ set.setM(reinterpret_cast<Heap::Base *>(setter));
}
Property &operator=(Value v) { value = v; return *this; }
private:
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 0a1aa56aab..d1796f5fd4 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>
@@ -92,7 +93,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)
@@ -235,8 +236,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
@@ -255,7 +256,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)
@@ -266,8 +267,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)
@@ -317,13 +318,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);
@@ -333,16 +333,15 @@ 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());
- ScopedContext global(scope, scope.engine->rootContext());
- return QV4::QObjectMethod::create(global, object, property->coreIndex, qmlcontextobject);
+ ScopedContext global(scope, scope.engine->qmlContext());
+ return QV4::QObjectMethod::create(global, object, property->coreIndex);
} 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 {
@@ -360,31 +359,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);
}
}
@@ -435,21 +435,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()) {
@@ -460,25 +460,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
@@ -505,16 +505,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());
@@ -543,11 +543,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";
@@ -561,7 +561,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QLatin1String(valueType) +
QLatin1String(" to ") +
QLatin1String(targetTypeName);
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
}
@@ -634,7 +634,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();
@@ -646,14 +646,19 @@ 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))
+ setProperty(engine, d()->object, propertyIndex, value);
+}
+
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
+{
+ if (QQmlData::wasDeleted(object))
return;
- QQmlData *ddata = QQmlData::get(d()->object, /*create*/false);
+ QQmlData *ddata = QQmlData::get(object, /*create*/false);
if (!ddata)
return;
@@ -661,14 +666,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, 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();
@@ -684,10 +689,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);
}
@@ -699,7 +704,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
@@ -718,23 +723,23 @@ 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);
}
-void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
// Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
@@ -745,10 +750,9 @@ 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();
+ name->setM(propName->d());
++it->arrayIndex;
*attributes = QV4::Attr_Data;
p->value = that->get(propName);
@@ -761,10 +765,9 @@ 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();
+ name->setM(methodName->d());
*attributes = QV4::Attr_Data;
p->value = that->get(methodName);
return;
@@ -811,7 +814,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>()) {
@@ -826,7 +829,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty()) {
QV4::ScopedString name(scope, f->name());
- error.setDescription(QString::fromLatin1("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
+ error.setDescription(QStringLiteral("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
}
if (QQmlEngine *qmlEngine = v4->qmlEngine()) {
QQmlEnginePrivate::get(qmlEngine)->warning(error);
@@ -1028,48 +1031,31 @@ void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e)
QV4::Object::markObjects(that, e);
}
-namespace {
- struct QObjectDeleter : public QV4::GCDeletable
- {
- QObjectDeleter(QObject *o)
- : m_objectToDelete(o)
- {}
- ~QObjectDeleter()
- {
- QQmlData *ddata = QQmlData::get(m_objectToDelete, false);
- if (ddata && ddata->ownContext && ddata->context)
- ddata->context->emitDestruction();
- // This object is notionally destroyed now
- ddata->isQueuedForDeletion = true;
- if (lastCall)
- delete m_objectToDelete;
- else
- m_objectToDelete->deleteLater();
- }
-
- QObject *m_objectToDelete;
- };
-}
-
-void QObjectWrapper::destroy(Heap::Base *that)
+void QObjectWrapper::destroyObject(bool lastCall)
{
- Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper*>(that);
- QPointer<QObject> object = This->object;
- ExecutionEngine *engine = This->internalClass->engine;
- This->~Data();
- This = 0;
- if (!object)
- return;
-
- QQmlData *ddata = QQmlData::get(object, false);
- if (!ddata)
- return;
-
- if (object->parent() || ddata->indestructible)
- return;
+ Heap::QObjectWrapper *h = d();
+ if (!h->internalClass)
+ return; // destroyObject already got called
+
+ QPointer<QObject> object = h->object;
+ if (object) {
+ QQmlData *ddata = QQmlData::get(object, false);
+ if (ddata) {
+ if (!object->parent() && !ddata->indestructible) {
+ if (ddata && ddata->ownContext && ddata->context)
+ ddata->context->emitDestruction();
+ // This object is notionally destroyed now
+ ddata->isQueuedForDeletion = true;
+ if (lastCall)
+ delete object;
+ else
+ object->deleteLater();
+ }
+ }
+ }
- QObjectDeleter *deleter = new QObjectDeleter(object);
- engine->memoryManager->registerDeletable(deleter);
+ h->internalClass = 0;
+ h->~Data();
}
@@ -1229,7 +1215,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;
@@ -1247,7 +1233,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;
@@ -1276,7 +1262,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;
@@ -1379,7 +1365,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (returnType == QMetaType::UnknownType) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method return type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method return type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1392,7 +1378,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (!args) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method parameter type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1606,9 +1592,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>()) {
@@ -1630,7 +1616,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);
}
@@ -1739,7 +1725,7 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
}
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal)
+ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index)
{
Scope valueScope(scope);
Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
@@ -1749,19 +1735,17 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in
method->d()->propertyCache = ddata->propertyCache;
method->d()->index = index;
- method->d()->qmlGlobal = qmlGlobal;
method->d()->valueTypeWrapper = Primitive::undefinedValue();
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)
{
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();
}
@@ -1777,7 +1761,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()) {
@@ -1803,7 +1787,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();
@@ -1822,13 +1806,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());
@@ -1876,11 +1860,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (method.isV4Function()) {
QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
-
- QV4::ScopedValue qmlGlobal(scope, d()->qmlGlobal);
- QQmlV4Function func(callData, rv, qmlGlobal,
- QmlContextWrapper::getContext(qmlGlobal),
- scope.engine);
+ QQmlV4Function func(callData, rv, scope.engine);
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
@@ -1899,7 +1879,6 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
{
QObjectMethod::Data *This = static_cast<QObjectMethod::Data*>(that);
- This->qmlGlobal.mark(e);
This->valueTypeWrapper.mark(e);
FunctionObject::markObjects(that, e);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 24e8b29e08..da24c81f40 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
@@ -79,7 +79,6 @@ struct QObjectMethod : FunctionObject {
QPointer<QObject> object;
QQmlRefPointer<QQmlPropertyCache> propertyCache;
int index;
- Value qmlGlobal;
Value valueTypeWrapper;
@@ -104,7 +103,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,26 +113,27 @@ 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);
+ static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value);
+ void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value);
+
+ void destroyObject(bool lastCall);
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);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
- static void destroy(Heap::Base *that);
static ReturnedValue method_connect(CallContext *ctx);
static ReturnedValue method_disconnect(CallContext *ctx);
@@ -148,18 +148,18 @@ 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, QObject *object, int index);
+ static ReturnedValue create(QV4::ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index);
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 b66e917b87..9316223696 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -40,12 +40,15 @@
#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"
#include "qv4scopedvalue_p.h"
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmltypewrapper_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include "qv4qobjectwrapper_p.h"
#include <private/qv8engine_p.h>
#endif
@@ -313,14 +316,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 +383,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 +396,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 +416,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 +440,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 +453,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();
@@ -467,7 +470,7 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -481,14 +484,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();
@@ -498,7 +501,7 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -578,7 +581,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();
}
@@ -912,7 +915,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);
@@ -934,7 +937,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)
@@ -943,13 +946,37 @@ 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);
}
return o->call(callData);
}
+ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
+ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
@@ -1037,7 +1064,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();
@@ -1046,7 +1073,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();
@@ -1092,24 +1119,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();
@@ -1202,7 +1229,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;
@@ -1242,7 +1269,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();
@@ -1327,34 +1354,16 @@ unsigned Runtime::doubleToUInt(const double &d)
return Primitive::toUInt32(d);
}
-#ifndef V4_BOOTSTRAP
-
-ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
-{
- return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
-}
-
-ReturnedValue Runtime::getQmlIdArray(NoThrowEngine *engine)
+ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine)
{
- Q_ASSERT(engine->qmlContextObject());
- Scope scope(engine);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->idObjectsArray();
+ return engine->qmlContext()->asReturnedValue();
}
-ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine)
-{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
- if (!context)
- return Encode::undefined();
- return QObjectWrapper::wrap(engine, context->contextObject);
-}
+#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::getQmlScopeObject(NoThrowEngine *engine)
+ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- return QObjectWrapper::wrap(engine, c->getScopeObject());
+ return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1365,21 +1374,29 @@ 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::getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false);
+}
+
+ReturnedValue Runtime::getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, false);
}
ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1390,8 +1407,34 @@ 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);
+}
+
+ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index)
+{
+ Scope scope(engine);
+ const QmlContext &qmlContext = static_cast<const QmlContext &>(c);
+ QQmlContextData *context = qmlContext.d()->qml->context;
+ if (!context || index >= (uint)context->idValueCount)
+ return Encode::undefined();
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ if (ep && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[index].bindings);
+
+ return QObjectWrapper::wrap(engine, context->idValues[index].data());
+}
+
+void Runtime::setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->scopeObject, propertyIndex, value);
+}
+
+void Runtime::setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value);
}
void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)
@@ -1402,13 +1445,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();
@@ -1418,8 +1460,7 @@ QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowEngine *engine, int name
{
Scope scope(engine);
ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->qmlSingletonWrapper(engine, name);
+ return engine->qmlSingletonWrapper(name);
}
void Runtime::convertThisToObject(ExecutionEngine *engine)
@@ -1428,7 +1469,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..f597e4b2e3 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>
@@ -90,6 +91,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// call
static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
+ static ReturnedValue callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
static ReturnedValue callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
static ReturnedValue callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callElement(ExecutionEngine *engine, const Value &index, CallData *callData);
@@ -206,19 +209,23 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static unsigned doubleToUInt(const double &d);
// qml
- static ReturnedValue getQmlIdArray(NoThrowEngine *ctx);
- static ReturnedValue getQmlImportedScripts(NoThrowEngine *ctx);
- static ReturnedValue getQmlContextObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlScopeObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlSingleton(NoThrowEngine *ctx, int nameIndex);
+ static ReturnedValue getQmlContext(NoThrowEngine *engine);
+ static ReturnedValue getQmlImportedScripts(NoThrowEngine *engine);
+ static ReturnedValue getQmlSingleton(NoThrowEngine *engine, int nameIndex);
static ReturnedValue getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex);
+ static ReturnedValue getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
+ static ReturnedValue getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
static ReturnedValue getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
static ReturnedValue getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
+ static ReturnedValue getQmlIdObject(ExecutionEngine *engine, const Value &context, uint index);
+
+ static void setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
+ static void setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
static void setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value);
};
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 +250,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);
@@ -262,7 +269,7 @@ inline ReturnedValue Runtime::uPlus(const Value &value)
if (value.isNumber())
return value.asReturnedValue();
if (value.integerCompatible())
- return Encode(value.int_32);
+ return Encode(value.int_32());
double n = value.toNumberImpl();
return Encode(n);
@@ -369,6 +376,15 @@ inline ReturnedValue Runtime::div(const Value &left, const Value &right)
{
TRACE2(left, right);
+ if (Value::integerCompatible(left, right)) {
+ int lval = left.integerValue();
+ int rval = right.integerValue();
+ if (rval != 0 && (lval % rval == 0))
+ return Encode(int(lval / rval));
+ else
+ return Encode(double(lval) / rval);
+ }
+
double lval = left.toNumber();
double rval = right.toNumber();
return Primitive::fromDouble(lval / rval).asReturnedValue();
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 908248f0f0..e19aeaf882 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 {
@@ -110,7 +107,7 @@ struct ScopedValue
ScopedValue(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = 0;
+ ptr->setRawValue(0);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -128,9 +125,9 @@ struct ScopedValue
ScopedValue(const Scope &scope, Heap::Base *o)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = o;
+ ptr->setM(o);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
#ifndef QT_NO_DEBUG
++scope.size;
@@ -140,7 +137,7 @@ struct ScopedValue
ScopedValue(const Scope &scope, Managed *m)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = m->asReturnedValue();
+ ptr->setRawValue(m->asReturnedValue());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -149,7 +146,7 @@ struct ScopedValue
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = v;
+ ptr->setRawValue(v);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -161,9 +158,9 @@ struct ScopedValue
}
ScopedValue &operator=(Heap::Base *o) {
- ptr->m = o;
+ ptr->setM(o);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
return *this;
}
@@ -174,7 +171,7 @@ struct ScopedValue
}
ScopedValue &operator=(const ReturnedValue &v) {
- ptr->val = v;
+ ptr->setRawValue(v);
return *this;
}
@@ -202,30 +199,29 @@ struct Scoped
{
enum _Convert { Convert };
- inline void setPointer(Managed *p) {
- ptr->m = p ? p->m : 0;
+ inline void setPointer(const Managed *p) {
+ ptr->setM(p ? p->m() : 0);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
Scoped(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = 0;
+ ptr->setM(0);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
#ifndef QT_NO_DEBUG
++scope.size;
#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
@@ -252,7 +248,7 @@ struct Scoped
Scoped(const Scope &scope, const Value &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, v);
+ ptr->setRawValue(value_convert<T>(scope.engine, v));
#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
@@ -295,16 +291,14 @@ struct Scoped
Scoped(const Scope &scope, const ReturnedValue &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v));
+ ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
}
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;
}
@@ -347,21 +341,21 @@ struct Scoped
}
bool operator!() const {
- return !ptr->m;
+ return !ptr->m();
}
operator void *() const {
- return ptr->m;
+ return ptr->m();
}
T *getPointer() {
return ptr->cast<T>();
}
- typename T::Data **getRef() {
- return reinterpret_cast<typename T::Data **>(&ptr->m);
+ Value *getRef() {
+ return ptr;
}
ReturnedValue asReturnedValue() const {
- return ptr->m ? ptr->val : Encode::undefined();
+ return ptr->m() ? ptr->rawValue() : Encode::undefined();
}
Value *ptr;
@@ -390,41 +384,14 @@ struct ScopedCallData {
inline Value &Value::operator =(const ScopedValue &v)
{
- val = v.ptr->val;
+ _val = v.ptr->val();
return *this;
}
template<typename T>
inline Value &Value::operator=(const Scoped<T> &t)
{
- val = t.ptr->val;
- 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;
+ _val = t.ptr->val();
return *this;
}
@@ -453,18 +420,18 @@ struct ExecutionContextSaver
: engine(context->d()->engine)
, savedContext(scope.alloc(1))
{
- savedContext->m = context->d();
+ savedContext->setM(context->d());
#if QT_POINTER_SIZE == 4
- savedContext->tag = QV4::Value::Managed_Type;
+ savedContext->setTag(QV4::Value::Managed_Type);
#endif
}
ExecutionContextSaver(Scope &scope, Heap::ExecutionContext *context)
: engine(context->engine)
, savedContext(scope.alloc(1))
{
- savedContext->m = context;
+ savedContext->setM(context);
#if QT_POINTER_SIZE == 4
- savedContext->tag = QV4::Value::Managed_Type;
+ savedContext->setTag(QV4::Value::Managed_Type);
#endif
}
~ExecutionContextSaver()
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 4fde0e2445..14b8b878bd 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -32,11 +32,12 @@
****************************************************************************/
#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"
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -44,6 +45,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,9 +88,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)
- , qml(qml->d())
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
{
Q_ASSERT(scope->inUse());
@@ -97,64 +98,50 @@ 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)
- , qml(qml->d())
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::QmlContextWrapper *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
{
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));
- return result->asReturnedValue();
-}
+ ExecutionContextSaver ctxSaver(scope, context);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f));
-void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e)
-{
- QmlBindingWrapper::Data *wrapper = static_cast<QmlBindingWrapper::Data *>(m);
- if (wrapper->qml)
- wrapper->qml->mark(e);
- FunctionObject::markObjects(m, e);
- if (wrapper->qmlContext)
- wrapper->qmlContext->mark(e);
+ return result->asReturnedValue();
}
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 +150,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 +201,7 @@ void Script::parse()
parsed = true;
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -285,7 +272,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 +280,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);
+ return Q_V4_PROFILE(engine, vmFunction);
} 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,15 +362,14 @@ 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();
}
-QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
+QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
{
QV4::Scope scope(engine);
QV4::Script qmlScript(engine, scopeObject, script, QString());
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 05a9e45f45..22714496f8 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -63,7 +63,7 @@ struct ContextStateSaver {
, compilationUnit(context->d()->compilationUnit)
, lineNumber(context->d()->lineNumber)
{
- savedContext->m = context->d();
+ savedContext->setM(context->d());
}
ContextStateSaver(Scope &scope, Heap::ExecutionContext *context)
: savedContext(scope.alloc(1))
@@ -72,12 +72,12 @@ struct ContextStateSaver {
, compilationUnit(context->compilationUnit)
, lineNumber(context->lineNumber)
{
- savedContext->m = context;
+ savedContext->setM(context);
}
~ContextStateSaver()
{
- Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m);
+ Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m());
ctx->strictMode = strictMode;
ctx->lookups = lookups;
ctx->compilationUnit = compilationUnit;
@@ -87,11 +87,9 @@ 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);
};
}
@@ -99,21 +97,18 @@ struct QmlBindingWrapper : Heap::FunctionObject {
struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
V4_OBJECT2(QmlBindingWrapper, FunctionObject)
- static ReturnedValue call(Managed *that, CallData *);
- static void markObjects(Heap::Base *m, ExecutionEngine *e);
+ static ReturnedValue call(const Managed *that, CallData *callData);
- 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 +120,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..23bbcc60e1 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) {
@@ -316,9 +316,9 @@ public:
return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
- void containerAdvanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
if (d()->isReference) {
@@ -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)
@@ -536,7 +536,7 @@ public:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static void advanceIterator(Managed *that, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ static void advanceIterator(Managed *that, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{ return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
};
@@ -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 31d85df13e..33b40796a4 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 6d55eb2c18..24a13ddd10 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"
@@ -110,7 +110,7 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (t == o)
return true;
- if (!o->d()->vtable->isString)
+ if (!o->d()->vtable()->isString)
return false;
return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o));
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 1cf8f51a29..93a25d7ed5 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -188,6 +188,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..9fbafa7ded 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>
@@ -70,44 +70,45 @@ DEFINE_OBJECT_VTABLE(StringObject);
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();
+ Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
+ 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;
@@ -115,20 +116,21 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
return true;
}
-void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(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..aa56a79bc3 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,14 +62,17 @@ 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);
protected:
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -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 19e541dba8..f06eeb08b9 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
@@ -257,7 +258,7 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
TypedArrayWrite write =array->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*destElementSize, val);
}
}
@@ -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();
@@ -523,7 +524,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
TypedArrayWrite write = a->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*elementSize, val);
}
@@ -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..4c81199a07 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,10 +69,32 @@ 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())
- return int_32;
+ return int_32();
return Primitive::toInteger(toNumber());
}
@@ -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();
@@ -99,7 +122,7 @@ double Value::toNumberImpl() const
case QV4::Value::Null_Type:
case QV4::Value::Boolean_Type:
case QV4::Value::Integer_Type:
- return int_32;
+ return int_32();
default: // double
Q_UNREACHABLE();
}
@@ -148,7 +171,7 @@ QString Value::toQStringNoThrow() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -184,7 +207,7 @@ QString Value::toQString() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -197,14 +220,14 @@ QString Value::toQString() const
#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
- if (val == other.val)
+ if (_val == other._val)
return true;
if (isString() && other.isString())
return stringValue()->isEqualTo(other.stringValue());
if (isInteger() && other.isDouble())
- return int_32 ? (double(int_32) == other.doubleValue()) : (other.val == 0);
+ return int_32() ? (double(int_32()) == other.doubleValue()) : (other._val == 0);
if (isDouble() && other.isInteger())
- return other.int_32 ? (doubleValue() == double(other.int_32)) : (val == 0);
+ return other.int_32() ? (doubleValue() == double(other.int_32())) : (_val == 0);
return false;
}
@@ -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 f3026900d6..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;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- 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
-{
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- 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 628950784a..6305e6dfbb 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -37,6 +37,7 @@
#include <QtCore/QString>
#include "qv4global_p.h"
+#include <private/qv4heap_p.h>
/* We cannot rely on QT_POINTER_SIZE to be set correctly on host builds. In qmldevtools the Value objects
are only used to store primitives, never object pointers. So we can use the 64-bit encoding. */
@@ -50,56 +51,12 @@ 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
{
/*
@@ -124,30 +81,38 @@ struct Q_QML_PRIVATE_EXPORT Value
Bit 15-17 is then used to encode other immediates.
*/
+ quint64 _val;
+
+ Q_ALWAYS_INLINE quint64 val() const { return _val; }
+ Q_ALWAYS_INLINE void setVal(quint64 v) { _val = v; }
+ Q_ALWAYS_INLINE void setValue(quint32 v) { setTagValue(tag(), v); }
+ Q_ALWAYS_INLINE void setTag(quint32 t) { setTagValue(t, value()); }
- union {
- quint64 val;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#else
- double dbl;
-#endif
- struct {
-#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
- uint tag;
-#endif
- union {
- uint uint_32;
- int int_32;
-#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#endif
- };
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- uint tag;
+ static inline int valueOffset() { return 0; }
+ static inline int tagOffset() { return 4; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
+ Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
+#else // !Q_LITTLE_ENDIAN
+ static inline int valueOffset() { return 4; }
+ static inline int tagOffset() { return 0; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 value() const { return _val >> 32; }
#endif
- };
- };
+
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); }
+#else // !QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); }
+#endif
+
+ Q_ALWAYS_INLINE int int_32() const { int i; quint32 v = value(); memcpy(&i, &v, 4); return i; }
+ Q_ALWAYS_INLINE void setInt_32(int i) { quint32 u; memcpy(&u, &i, 4); setValue(u); }
+ Q_ALWAYS_INLINE uint uint_32() const { return value(); }
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
enum Masks {
@@ -220,127 +185,127 @@ struct Q_QML_PRIVATE_EXPORT Value
#endif
inline unsigned type() const {
- return tag & Type_Mask;
+ return tag() & Type_Mask;
}
// used internally in property
- inline bool isEmpty() const { return tag == Empty_Type; }
+ inline bool isEmpty() const { return tag() == Empty_Type; }
- inline bool isUndefined() const { return tag == Undefined_Type; }
- inline bool isNull() const { return tag == _Null_Type; }
- inline bool isBoolean() const { return tag == _Boolean_Type; }
+ inline bool isUndefined() const { return tag() == Undefined_Type; }
+ inline bool isNull() const { return tag() == _Null_Type; }
+ inline bool isBoolean() const { return tag ()== _Boolean_Type; }
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
- inline bool isDouble() const { return (val >> IsDouble_Shift); }
- inline bool isNumber() const { return (val >> IsNumber_Shift); }
- inline bool isManaged() const { return !(val >> IsManaged_Shift); }
- inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
- inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
+ inline bool isInteger() const { return (_val >> IsNumber_Shift) == 1; }
+ inline bool isDouble() const { return (_val >> IsDouble_Shift); }
+ inline bool isNumber() const { return (_val >> IsNumber_Shift); }
+ inline bool isManaged() const { return !(_val >> IsManaged_Shift); }
+ inline bool isNullOrUndefined() const { return ((_val >> IsManaged_Shift) & ~2) == 1; }
+ inline bool integerCompatible() const { return ((_val >> IsConvertibleToInt_Shift) & ~2) == 1; }
static inline bool integerCompatible(Value a, Value b) {
return a.integerCompatible() && b.integerCompatible();
}
static inline bool bothDouble(Value a, Value b) {
return a.isDouble() && b.isDouble();
}
- double doubleValue() const {
- Q_ASSERT(isDouble());
- union {
- quint64 i;
- double d;
- } v;
- v.i = val ^ NaNEncodeMask;
- return v.d;
- }
- void setDouble(double d) {
- union {
- quint64 i;
- double d;
- } v;
- v.d = d;
- val = v.i ^ NaNEncodeMask;
- Q_ASSERT(isDouble());
- }
- inline bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
+ inline bool isNaN() const { return (tag() & 0x7fff8000) == 0x00078000; }
#else
- inline bool isInteger() const { return tag == _Integer_Type; }
- inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isManaged() const { return tag == Managed_Type; }
- inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
- inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
+ inline bool isInteger() const { return tag() == _Integer_Type; }
+ inline bool isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isNumber() const { return tag() == _Integer_Type || (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isManaged() const { return tag() == Managed_Type; }
+ inline bool isNullOrUndefined() const { return (tag() & IsNullOrUndefined_Mask) == Undefined_Type; }
+ inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; }
static inline bool integerCompatible(Value a, Value b) {
- return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
+ return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt;
}
static inline bool bothDouble(Value a, Value b) {
- return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
+ return ((a.tag() | b.tag()) & NotDouble_Mask) != NotDouble_Mask;
}
- double doubleValue() const { Q_ASSERT(isDouble()); return dbl; }
- void setDouble(double d) { dbl = d; Q_ASSERT(isDouble()); }
- inline bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
+ inline bool isNaN() const { return (tag() & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
#endif
+ Q_ALWAYS_INLINE double doubleValue() const {
+ Q_ASSERT(isDouble());
+ double d;
+ quint64 v = _val;
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ v ^= NaNEncodeMask;
+#endif
+ memcpy(&d, &v, 8);
+ return d;
+ }
+ Q_ALWAYS_INLINE void setDouble(double d) {
+ memcpy(&_val, &d, 8);
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ _val ^= NaNEncodeMask;
+#endif
+ Q_ASSERT(isDouble());
+ }
inline bool isString() const;
inline bool isObject() const;
inline bool isInt32() {
- if (tag == _Integer_Type)
+ if (tag() == _Integer_Type)
return true;
if (isDouble()) {
double d = doubleValue();
int i = (int)d;
if (i == d) {
- int_32 = i;
- tag = _Integer_Type;
+ setInt_32(i);
+ setTag(_Integer_Type);
return true;
}
}
return false;
}
double asDouble() const {
- if (tag == _Integer_Type)
- return int_32;
+ if (tag() == _Integer_Type)
+ return int_32();
return doubleValue();
}
bool booleanValue() const {
- return int_32;
+ return int_32();
}
int integerValue() const {
- return int_32;
+ return int_32();
}
- String *stringValue() const {
- return m ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE String *stringValue() const {
+ return m() ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
}
- Object *objectValue() const {
- return m ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Object *objectValue() const {
+ return m() ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
}
- Managed *managed() const {
- return m ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Managed *managed() const {
+ return m() ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
}
- Heap::Base *heapObject() const {
- return m;
+ Q_ALWAYS_INLINE Heap::Base *heapObject() const {
+ return m();
}
- quint64 rawValue() const {
- return val;
+ Q_ALWAYS_INLINE quint64 &rawValueRef() {
+ return _val;
+ }
+ Q_ALWAYS_INLINE quint64 rawValue() const {
+ return _val;
}
+ Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
static inline Value fromHeapObject(Heap::Base *m)
{
Value v;
- v.m = m;
+ v.setRawValue(0);
+ v.setM(m);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- v.tag = Managed_Type;
+ v.setTag(Managed_Type);
#endif
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;
@@ -353,21 +318,32 @@ struct Q_QML_PRIVATE_EXPORT Value
inline bool tryIntegerConversion() {
bool b = integerCompatible();
if (b)
- tag = _Integer_Type;
+ setTag(_Integer_Type);
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());
}
@@ -376,26 +352,32 @@ 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; }
+ ReturnedValue asReturnedValue() const { return _val; }
+ static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; }
// 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=(ReturnedValue v) { _val = v; return *this; }
Value &operator=(Managed *m) {
- val = Value::fromManaged(m).val;
+ if (!m) {
+ setTagValue(Undefined_Type, 0);
+ } else {
+ _val = reinterpret_cast<Value *>(m)->_val;
+ }
return *this;
}
Value &operator=(Heap::Base *o) {
- m = o;
+ setM(o);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ setTag(Managed_Type);
#endif
return *this;
}
@@ -403,17 +385,68 @@ struct Q_QML_PRIVATE_EXPORT Value
template<typename T>
Value &operator=(const Scoped<T> &t);
Value &operator=(const Value &v) {
- val = v.val;
+ _val = v._val;
return *this;
}
};
-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 (isManaged())
- return managed();
- return 0;
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ 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
+{
+ return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
+}
+
+
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
@@ -437,10 +470,11 @@ inline Primitive Primitive::undefinedValue()
{
Primitive v;
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- v.val = quint64(Undefined_Type) << Tag_Shift;
+ v.setRawValue(quint64(Undefined_Type) << Tag_Shift);
#else
- v.tag = Undefined_Type;
- v.int_32 = 0;
+ v.setRawValue(0);
+ v.setTag(Undefined_Type);
+ v.setValue(0);
#endif
return v;
}
@@ -448,39 +482,54 @@ inline Primitive Primitive::undefinedValue()
inline Primitive Primitive::emptyValue()
{
Primitive v;
- v.tag = Value::Empty_Type;
- v.uint_32 = 0;
+ v.setTagValue(Value::Empty_Type, 0);
return v;
}
-template <typename T>
-struct TypedValue : public Value
+inline Primitive Primitive::nullValue()
{
- template<typename X>
- TypedValue &operator =(X *x) {
- m = x;
+ Primitive v;
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ v.setRawValue(quint64(_Null_Type) << Tag_Shift);
+#else
+ v.setTagValue(_Null_Type, 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.setTagValue(_Boolean_Type, 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.setTagValue(_Integer_Type, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32(i);
+ return v;
+}
+inline Primitive Primitive::fromUInt32(uint i)
+{
+ Primitive v;
+ if (i < INT_MAX) {
+ v.setTagValue(_Integer_Type, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32((int)i);
+ } else {
+ v.setDouble(i);
+ }
+ return v;
+}
struct Encode {
static ReturnedValue undefined() {
@@ -496,7 +545,7 @@ struct Encode {
Encode(double d) {
Value v;
v.setDouble(d);
- val = v.val;
+ val = v.rawValue();
}
Encode(int i) {
val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | (uint)i;
@@ -507,7 +556,7 @@ struct Encode {
} else {
Value v;
v.setDouble(i);
- val = v.val;
+ val = v.rawValue();
}
}
Encode(ReturnedValue v) {
@@ -527,21 +576,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..f9e26efe71 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)
@@ -129,7 +129,7 @@ QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx)
return Encode::undefined();
QString result = o->d()->data.toString();
if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String))
- result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
+ result = QStringLiteral("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
return Encode(ctx->d()->engine->newString(result));
}
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 390bbf5ee3..0edd7378a7 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"
@@ -512,6 +513,28 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
+ MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
+ Runtime::setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(StoreContextObjectProperty)
+ Runtime::setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadContextObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadIdObject)
+ STOREVALUE(instr.result, Runtime::getQmlIdObject(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(LoadIdObject)
+
MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex));
MOTH_END_INSTR(LoadAttachedQObjectProperty)
@@ -565,6 +588,26 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData));
MOTH_END_INSTR(CallPropertyLookup)
+ MOTH_BEGIN_INSTR(CallScopeObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(CallContextObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlContextObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallContextObjectProperty)
+
MOTH_BEGIN_INSTR(CallElement)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
@@ -858,28 +901,20 @@ 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();
MOTH_END_INSTR(LoadThis)
- MOTH_BEGIN_INSTR(LoadQmlIdArray)
- VALUE(instr.result) = Runtime::getQmlIdArray(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadQmlIdArray)
+ MOTH_BEGIN_INSTR(LoadQmlContext)
+ VALUE(instr.result) = Runtime::getQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
+ MOTH_END_INSTR(LoadQmlContext)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
- MOTH_BEGIN_INSTR(LoadQmlContextObject)
- VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadContextObject)
-
- MOTH_BEGIN_INSTR(LoadQmlScopeObject)
- VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadScopeObject)
-
MOTH_BEGIN_INSTR(LoadQmlSingleton)
VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
MOTH_END_INSTR(LoadQmlSingleton)
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..a93e4191b0
--- /dev/null
+++ b/src/qml/memory/qv4heap_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** 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 {
+ quintptr mm_data; // vtable and markbit
+
+ inline ReturnedValue asReturnedValue() const;
+ inline void mark(QV4::ExecutionEngine *engine);
+
+ enum {
+ MarkBit = 0x1,
+ NotInUse = 0x2,
+ PointerMask = ~0x3
+ };
+
+ void setVtable(const VTable *v) {
+ Q_ASSERT(!(mm_data & MarkBit));
+ mm_data = reinterpret_cast<quintptr>(v);
+ }
+ VTable *vtable() 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 64491e1376..b880c9c8d5 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -111,8 +111,6 @@ struct MemoryManager::Data
LargeItem *largeItems;
std::size_t totalLargeItemsAllocated;
- GCDeletable *deletable;
-
// statistics:
#ifdef DETAILED_MM_STATS
QVector<unsigned> allocSizeCounters;
@@ -129,7 +127,6 @@ struct MemoryManager::Data
, unmanagedHeapSizeGCLimit(64 * 1024)
, largeItems(0)
, totalLargeItemsAllocated(0)
- , deletable(0)
{
memset(nonFullChunks, 0, sizeof(nonFullChunks));
memset(nChunks, 0, sizeof(nChunks));
@@ -189,15 +186,15 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
#ifdef V4_USE_VALGRIND
VALGRIND_ENABLE_ERROR_REPORTING;
#endif
- if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->gcGetVtable()->isString) {
+ if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->vtable()->isString) {
std::size_t heapBytes = static_cast<Heap::String *>(m)->retainedTextSize();
Q_ASSERT(*unmanagedHeapSize >= heapBytes);
// qDebug() << "-- it's a string holding on to" << heapBytes << "bytes";
*unmanagedHeapSize -= heapBytes;
}
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
+ if (m->vtable()->destroy)
+ m->vtable()->destroy(m);
memset(m, 0, header->itemSize);
#ifdef V4_USE_VALGRIND
@@ -307,7 +304,6 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
m_d->heapChunks.append(allocation);
- std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end());
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
header->itemSize = int(size);
@@ -353,8 +349,8 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
+ Q_ASSERT (h->vtable()->markObjects);
+ h->vtable()->markObjects(h, engine);
}
}
@@ -377,11 +373,9 @@ void MemoryManager::mark()
for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
if (!(*it).isManaged())
continue;
- if ((*it).managed()->d()->gcGetVtable() != QObjectWrapper::staticVTable())
+ if (!(*it).as<QObjectWrapper>())
continue;
QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed());
- if (!qobjectWrapper)
- continue;
QObject *qobject = qobjectWrapper->object();
if (!qobject)
continue;
@@ -408,13 +402,18 @@ void MemoryManager::mark()
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 (!m->markBit())
- (*it) = Primitive::undefinedValue();
- }
- }
+ for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
+ if (!(*it).isManaged())
+ continue;
+ Managed *m = (*it).as<Managed>();
+ if (m->markBit())
+ continue;
+ // we need to call detroyObject on qobjectwrappers now, so that they can emit the destroyed
+ // signal before we start sweeping the heap
+ if (QObjectWrapper *qobjectWrapper = (*it).as<QObjectWrapper>())
+ qobjectWrapper->destroyObject(lastSweep);
+
+ (*it) = Primitive::undefinedValue();
}
if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
@@ -473,8 +472,8 @@ void MemoryManager::sweep(bool lastSweep)
i = i->next;
continue;
}
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
+ if (m->vtable()->destroy)
+ m->vtable()->destroy(m);
*last = i->next;
free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
@@ -482,15 +481,6 @@ void MemoryManager::sweep(bool lastSweep)
i = *last;
}
- GCDeletable *deletable = m_d->deletable;
- m_d->deletable = 0;
- while (deletable) {
- GCDeletable *next = deletable->next;
- deletable->lastCall = lastSweep;
- delete deletable;
- deletable = next;
- }
-
// some execution contexts are allocated on the stack, make sure we clear their markBit as well
if (!lastSweep) {
Heap::ExecutionContext *ctx = engine()->current;
@@ -554,7 +544,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);
@@ -590,10 +580,10 @@ void MemoryManager::growUnmanagedHeapSizeUsage(size_t delta)
MemoryManager::~MemoryManager()
{
delete m_persistentValues;
- delete m_weakValues;
- m_weakValues = 0;
sweep(/*lastSweep*/true);
+
+ delete m_weakValues;
#ifdef V4_USE_VALGRIND
VALGRIND_DESTROY_MEMPOOL(this);
#endif
@@ -618,12 +608,6 @@ void MemoryManager::dumpStats() const
#endif // DETAILED_MM_STATS
}
-void MemoryManager::registerDeletable(GCDeletable *d)
-{
- d->next = m_d->deletable;
- m_d->deletable = d;
-}
-
#ifdef DETAILED_MM_STATS
void MemoryManager::willAllocate(std::size_t size)
{
@@ -641,7 +625,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 7f6d2edba3..c01866ff11 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
@@ -87,7 +87,7 @@ public:
{
size = align(size);
Heap::Base *o = allocData(size, unmanagedSize);
- o->vtable = ManagedType::staticVTable();
+ o->setVtable(ManagedType::staticVTable());
return static_cast<typename ManagedType::Data *>(o);
}
@@ -162,8 +162,6 @@ public:
void dumpStats() const;
- void registerDeletable(GCDeletable *d);
-
size_t getUsedMem() const;
size_t getAllocatedMem() const;
size_t getLargeItemsMem() const;
diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h
index 16927251c7..c7ac5919bd 100644
--- a/src/qml/parser/qqmljsmemorypool_p.h
+++ b/src/qml/parser/qqmljsmemorypool_p.h
@@ -104,28 +104,6 @@ public:
template <typename _Tp> _Tp *New() { return new (this->allocate(sizeof(_Tp))) _Tp(); }
- template <typename PoolContentType, typename Visitor>
- void visitManagedPool(Visitor &visitor)
- {
- for (int i = 0; i <= _blockCount; ++i) {
- char *p = _blocks[i];
- char *end = p + BLOCK_SIZE;
- if (i == _blockCount) {
- Q_ASSERT(_ptr <= end);
- end = _ptr;
- }
-
- Q_ASSERT(p <= end);
-
- const qptrdiff increment = (sizeof(PoolContentType) + 7) & ~7;
-
- while (p + increment <= end) {
- visitor(reinterpret_cast<PoolContentType*>(p));
- p += increment;
- }
- }
- }
-
private:
void *allocate_helper(size_t size)
{
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/ftw.pri b/src/qml/qml/ftw/ftw.pri
index 4b109107f9..51697b0aff 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -4,7 +4,6 @@ HEADERS += \
$$PWD/qpodvector_p.h \
$$PWD/qhashedstring_p.h \
$$PWD/qqmlrefcount_p.h \
- $$PWD/qqmlpool_p.h \
$$PWD/qfieldlist_p.h \
$$PWD/qhashfield_p.h \
$$PWD/qqmlthread_p.h \
@@ -20,7 +19,6 @@ HEADERS += \
SOURCES += \
$$PWD/qintrusivelist.cpp \
$$PWD/qhashedstring.cpp \
- $$PWD/qqmlpool.cpp \
$$PWD/qqmlthread.cpp \
# mirrors logic in $$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri
diff --git a/src/qml/qml/ftw/qqmlpool_p.h b/src/qml/qml/ftw/qqmlpool_p.h
deleted file mode 100644
index 4956cd81d8..0000000000
--- a/src/qml/qml/ftw/qqmlpool_p.h
+++ /dev/null
@@ -1,270 +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 QQMLPOOL_P_H
-#define QQMLPOOL_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/qv4global_p.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qurl.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlPool
-{
-public:
- // The class has a destructor that needs to be called
- class Class {
- public:
- inline QQmlPool *pool() const;
-
- private:
- void *operator new(size_t);
- void *operator new(size_t, void *m) { return m; }
- friend class QQmlPool;
-
- QQmlPool *_pool;
- Class *_next;
- void (*_destroy)(Class *);
- };
-
- // The class is plain old data and no destructor needs to
- // be called
- class POD {
- public:
- inline QQmlPool *pool() const;
-
- private:
- void *operator new(size_t);
- void *operator new(size_t, void *m) { return m; }
- friend class QQmlPool;
-
- QQmlPool *_pool;
- };
-
- inline QQmlPool();
- inline ~QQmlPool();
-
- void clear();
-
- template<typename T>
- inline T *New();
- template<typename T>
- inline T *NewRaw();
- template<typename T>
- inline T *NewRawArray(int length);
-
- inline QString *NewString(const QString &);
- inline QByteArray *NewByteArray(const QByteArray &);
- inline QUrl *NewUrl(const QUrl &);
-
- template<typename T>
- struct List {
- List() : m_length(0), m_data(0) {}
- List(const List &o) : m_length(o.m_length), m_data(o.m_data) {}
- List &operator=(const List &o) {
- m_length = o.m_length;
- m_data = o.m_data;
- return *this;
- }
-
- int count() const {
- return m_length;
- }
- int length() const {
- return m_length;
- }
- const T &at(int index) const {
- Q_ASSERT(index < m_length);
- return m_data[index];
- };
- T &operator[](int index) {
- Q_ASSERT(index < m_length);
- return m_data[index];
- };
- const T *data() const { return m_data; }
- private:
- friend class QQmlPool;
- List(T *d, int l) : m_length(l), m_data(d) {}
- int m_length;
- T *m_data;
- };
-
- template<typename T>
- inline List<T> NewRawList(int length);
-
-private:
- struct StringClass : public QString, public Class {
- };
- struct ByteArrayClass : public QByteArray, public Class {
- };
- struct UrlClass : public QUrl, public Class {
- };
-
- inline void *allocate(int size);
- void newpage();
-
- template<typename T>
- inline void initialize(POD *);
- template<typename T>
- inline void initialize(Class *);
- template<typename T>
- static void destroy(Class *c);
-
- struct Page {
- struct Header {
- Page *next;
- char *free;
- } header;
-
- static const int pageSize = 4 * 4096 - sizeof(Header);
-
- char memory[pageSize];
- };
-
- Page *_page;
- Class *_classList;
-};
-
-QQmlPool::QQmlPool()
-: _page(0), _classList(0)
-{
-}
-
-QQmlPool::~QQmlPool()
-{
- clear();
-}
-
-template<typename T>
-T *QQmlPool::New()
-{
- T *rv = new (allocate(sizeof(T))) T;
- initialize<T>(rv);
- rv->_pool = this;
- return rv;
-}
-
-template<typename T>
-T *QQmlPool::NewRaw()
-{
- return (T*)allocate(sizeof(T));
-}
-
-template<typename T>
-T *QQmlPool::NewRawArray(int length)
-{
- return (T*)allocate(length * sizeof(T));
-}
-
-template<typename T>
-QQmlPool::List<T> QQmlPool::NewRawList(int length)
-{
- return List<T>(NewRawArray<T>(length), length);
-}
-
-QString *QQmlPool::NewString(const QString &s)
-{
- QString *rv = New<StringClass>();
- *rv = s;
- return rv;
-}
-
-QByteArray *QQmlPool::NewByteArray(const QByteArray &s)
-{
- QByteArray *rv = New<ByteArrayClass>();
- *rv = s;
- return rv;
-}
-
-QUrl *QQmlPool::NewUrl(const QUrl &s)
-{
- QUrl *rv = New<UrlClass>();
- *rv = s;
- return rv;
-}
-
-void *QQmlPool::allocate(int size)
-{
- if (!_page || (_page->header.free + size) > (_page->memory + Page::pageSize))
- newpage();
-
- void *rv = _page->header.free;
- _page->header.free += size + ((8 - size) & 7); // ensure 8 byte alignment;
- return rv;
-}
-
-template<typename T>
-void QQmlPool::initialize(QQmlPool::POD *)
-{
-}
-
-template<typename T>
-void QQmlPool::initialize(QQmlPool::Class *c)
-{
- c->_next = _classList;
- c->_destroy = &destroy<T>;
- _classList = c;
-}
-
-template<typename T>
-void QQmlPool::destroy(Class *c)
-{
- static_cast<T *>(c)->~T();
-}
-
-QQmlPool *QQmlPool::Class::pool() const
-{
- return _pool;
-}
-
-QQmlPool *QQmlPool::POD::pool() const
-{
- return _pool;
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLPOOL_P_H
-
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..4d84cc82ae 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -23,7 +23,6 @@ SOURCES += \
$$PWD/qqmlvaluetype.cpp \
$$PWD/qqmlaccessors.cpp \
$$PWD/qqmlxmlhttprequest.cpp \
- $$PWD/qqmlwatcher.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
$$PWD/qqmlnotifier.cpp \
@@ -35,7 +34,6 @@ SOURCES += \
$$PWD/qqmlimport.cpp \
$$PWD/qqmllist.cpp \
$$PWD/qqmllocale.cpp \
- $$PWD/qqmlabstractexpression.cpp \
$$PWD/qqmljavascriptexpression.cpp \
$$PWD/qqmlabstractbinding.cpp \
$$PWD/qqmlvaluetypeproxybinding.cpp \
@@ -92,7 +90,6 @@ HEADERS += \
$$PWD/qqmlvaluetype_p.h \
$$PWD/qqmlaccessors_p.h \
$$PWD/qqmlxmlhttprequest_p.h \
- $$PWD/qqmlwatcher_p.h \
$$PWD/qqmlcleanup_p.h \
$$PWD/qqmlpropertycache_p.h \
$$PWD/qqmlnotifier_p.h \
@@ -107,7 +104,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.cpp b/src/qml/qml/qqmlabstractexpression.cpp
deleted file mode 100644
index c55c86952c..0000000000
--- a/src/qml/qml/qqmlabstractexpression.cpp
+++ /dev/null
@@ -1,93 +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$
-**
-****************************************************************************/
-
-#include "qqmlabstractexpression_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QQmlAbstractExpression::QQmlAbstractExpression()
-: m_prevExpression(0), m_nextExpression(0)
-{
-}
-
-QQmlAbstractExpression::~QQmlAbstractExpression()
-{
- 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;
-}
-
-QQmlContextData *QQmlAbstractExpression::context() const
-{
- if (m_context.isT1()) return m_context.asT1();
- else return m_context.asT2()->_c;
-}
-
-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;
- }
-
- if (m_context.isT1()) m_context = context;
- else m_context.asT2()->_c = context;
-
- if (context) {
- m_nextExpression = context->expressions;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = &m_nextExpression;
- m_prevExpression = &context->expressions;
- context->expressions = this;
- }
-}
-
-void QQmlAbstractExpression::refresh()
-{
-}
-
-bool QQmlAbstractExpression::isValid() const
-{
- return context() != 0;
-}
-
-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..3613c17242 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -43,43 +43,28 @@
#include <private/qqmlscriptstring_p.h>
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
+#include <private/qqmlvmemetaobject_p.h>
+#include <private/qqmlvaluetypewrapper_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 +85,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 +148,243 @@ 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:
+ if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
+ if (vtw->d()->valueType->typeId == core.propType) {
+ return vtw->write(m_target.data(), core.coreIndex);
+ }
+ }
+ 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 *const *)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 +393,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 +403,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 +415,92 @@ 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;
+ 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..3d1a9f8a88 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -43,11 +43,12 @@
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
#include <private/qqmlprofiler_p.h>
-#include <private/qv4debugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#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 +56,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 +127,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 +143,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 +176,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 +197,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 +282,7 @@ void QQmlAbstractBoundSignal::addToObject(QObject *obj)
data->signalHandlers = this;
}
-void QQmlAbstractBoundSignal::removeFromObject()
+void QQmlBoundSignal::removeFromObject()
{
if (m_prevSignal) {
*m_prevSignal = m_nextSignal;
@@ -318,40 +292,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 +302,29 @@ 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 *service = QQmlDebugConnector::service<QV4DebugService>();
+ if (service)
+ service->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 +334,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..d62aada9c6 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -43,7 +43,8 @@
#include "qqmlengine.h"
#include "qqmlbinding_p.h"
#include "qqmlglobal_p.h"
-#include <private/qqmlenginedebugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include "qqmlincubator.h"
#include "qqmlincubator_p.h"
#include <private/qqmljavascriptexpression_p.h>
@@ -53,6 +54,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4objectiterator_p.h>
#include <QStack>
#include <QStringList>
@@ -61,23 +63,6 @@
#include <qqmlinfo.h>
#include "qqmlmemoryprofiler_p.h"
-#define INITIALPROPERTIES_SOURCE \
- "(function(object, values) {"\
- "try {"\
- "for (var property in values) {" \
- "try {"\
- "var properties = property.split(\".\");"\
- "var o = object;"\
- "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
- "o = o[properties[ii]];"\
- "}"\
- "o[properties[properties.length - 1]] = values[property];"\
- "} catch(e) {}"\
- "}"\
- "} catch(e) {}"\
- "})"
-
-
namespace {
QThreadStorage<int> creationDepth;
}
@@ -98,7 +83,6 @@ V4_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
\class QQmlComponent
\since 5.0
\inmodule QtQml
- \mainclass
\brief The QQmlComponent class encapsulates a QML component definition
@@ -896,10 +880,11 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
depthIncreased = false;
}
- if (enginePriv->isDebugging && rv) {
+ QQmlEngineDebugService *service = QQmlDebugConnector::service<QQmlEngineDebugService>();
+ if (service && rv) {
if (!context->isInternal)
context->asQQmlContextPrivate()->instances.append(rv);
- QQmlEngineDebugService::instance()->objectCreated(engine, rv);
+ service->objectCreated(engine, rv);
}
return rv;
@@ -1194,6 +1179,46 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
\sa incubateObject()
*/
+
+static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value &o, const QV4::Value &v)
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedObject object(scope);
+ QV4::ScopedObject valueMap(scope, v);
+ QV4::ObjectIterator it(scope, valueMap, QV4::ObjectIterator::EnumerableOnly|QV4::ObjectIterator::WithProtoChain);
+ QV4::ScopedString name(scope);
+ QV4::ScopedValue val(scope);
+ if (engine->hasException)
+ return;
+
+ while (1) {
+ name = it.nextPropertyNameAsString(val);
+ if (!name)
+ break;
+ object = o;
+ const QStringList properties = name->toQString().split(QLatin1Char('.'));
+ for (int i = 0; i < properties.length() - 1; ++i) {
+ name = engine->newString(properties.at(i));
+ object = object->get(name);
+ if (engine->hasException || !object) {
+ break;
+ }
+ }
+ if (engine->hasException || !object) {
+ engine->hasException = false;
+ continue;
+ }
+ name = engine->newString(properties.last());
+ object->put(name, val);
+ if (engine->hasException) {
+ engine->hasException = false;
+ continue;
+ }
+ }
+
+ engine->hasException = false;
+}
+
/*!
\internal
*/
@@ -1216,7 +1241,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;
@@ -1239,16 +1264,8 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv));
Q_ASSERT(object->isObject());
- 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());
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
- callData->args[0] = object;
- callData->args[1] = valuemap;
- f->asFunctionObject()->call(callData);
- }
+ if (!valuemap->isUndefined())
+ setInitialProperties(v4, object, valuemap);
d->completeCreate();
@@ -1256,10 +1273,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 +1356,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;
@@ -1383,25 +1397,17 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
}
// XXX used by QSGLoader
-void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate)
+void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate)
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4engine);
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate));
- Q_ASSERT(object->asObject());
-
- 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->args[0] = object;
- callData->args[1] = valuemap;
- f->call(callData);
- }
+ Q_ASSERT(object->as<QV4::Object>());
+
+ if (!valuemap.isUndefined())
+ setInitialProperties(v4engine, object, valuemap);
}
QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
@@ -1491,13 +1497,8 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
if (!d()->valuemap.isUndefined()) {
QV4::ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
-
- QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject()));
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
- callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
- callData->args[1] = d()->valuemap;
- f->call(callData);
+ QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
+ setInitialProperties(v4, obj, d()->valuemap);
}
}
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/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index adc6e173d2..15ec88dd52 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -82,7 +82,7 @@ public:
QObject *beginCreate(QQmlContextData *);
void completeCreate();
- void initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate);
+ void initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate);
QQmlTypeData *typeData;
virtual void typeDataReady(QQmlTypeData *);
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index fb51bad3a7..b056731e96 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..1007029416 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,17 @@ 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();
- 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 +113,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 +177,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 +186,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 +247,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,127 +310,4 @@ 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 :)
- Q_ASSERT(compiledFunction->hasQmlDependencies());
-
- QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
- if (!ep)
- return;
- QQmlEnginePrivate::PropertyCapture *capture = ep->propertyCapture;
- if (!capture)
- return;
-
- QV4::Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> contextWrapper(scope, engine->qmlContextObject());
- QQmlContextData *qmlContext = contextWrapper->getContext();
-
- const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
- const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
- for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
- Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
- capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
- }
-
- Q_ASSERT(qmlContext->contextObject);
- const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
- const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
- for (int i = 0; i < contextPropertyDependencyCount; ++i) {
- const int propertyIndex = *contextPropertyDependency++;
- const int notifyIndex = *contextPropertyDependency++;
- capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
- }
-
- QObject *scopeObject = contextWrapper->getScopeObject();
- const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
- const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
- for (int i = 0; i < scopePropertyDependencyCount; ++i) {
- const int propertyIndex = *scopePropertyDependency++;
- const int notifyIndex = *scopePropertyDependency++;
- capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
- }
-
-}
-
-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)
- return Encode::undefined();
- // Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = d()->context->imports->query(name);
-
- Q_ASSERT(r.isValid());
- Q_ASSERT(r.type);
- Q_ASSERT(r.type->isSingleton());
- Q_ASSERT(v4);
-
- QQmlEngine *e = v4->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
- siinfo->init(e);
-
- if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
- return QV4::QObjectWrapper::wrap(engine(), qobjectSingleton);
- 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 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();
- if (!context) {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
- if (index >= (uint)context->idValueCount) {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
-
- if (hasProperty)
- *hasProperty = true;
-
- QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
- if (ep)
- ep->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..192df9aed6 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,33 +86,17 @@ 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; }
- static QQmlContextData *getContext(const Value &value);
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);
-
};
}
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..57b50733ea 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -146,7 +146,7 @@ bool QQmlDirParser::parse(const QString &source)
if (invalidLine) {
reportError(lineNumber, 0,
- QString::fromLatin1("invalid qmldir directive contains too many tokens"));
+ QStringLiteral("invalid qmldir directive contains too many tokens"));
continue;
} else if (sectionCount == 0) {
continue; // no sections, no party.
@@ -154,17 +154,17 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("module")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
- QString::fromLatin1("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
if (!_typeNamespace.isEmpty()) {
reportError(lineNumber, 0,
- QString::fromLatin1("only one module identifier directive may be defined in a qmldir file"));
+ QStringLiteral("only one module identifier directive may be defined in a qmldir file"));
continue;
}
if (!firstLine) {
reportError(lineNumber, 0,
- QString::fromLatin1("module identifier directive must be the first directive in a qmldir file"));
+ QStringLiteral("module identifier directive must be the first directive in a qmldir file"));
continue;
}
@@ -173,7 +173,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("plugin")) {
if (sectionCount < 2 || sectionCount > 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
@@ -185,7 +185,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
Component entry(sections[1], sections[2], -1, -1);
@@ -194,7 +194,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("singleton")) {
if (sectionCount < 3 || sectionCount > 4) {
reportError(lineNumber, 0,
- QString::fromLatin1("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
} else if (sectionCount == 3) {
// handle qmldir directory listing case where singleton is defined in the following pattern:
@@ -218,7 +218,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("typeinfo")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
- QString::fromLatin1("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
#ifdef QT_CREATOR
@@ -228,13 +228,13 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("designersupported")) {
if (sectionCount != 1)
- reportError(lineNumber, 0, QString::fromLatin1("designersupported does not expect any argument"));
+ reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument"));
else
_designerSupported = true;
} else if (sections[0] == QLatin1String("depends")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
@@ -268,7 +268,7 @@ bool QQmlDirParser::parse(const QString &source)
}
} else {
reportError(lineNumber, 0,
- QString::fromLatin1("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
+ QStringLiteral("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
}
firstLine = false;
@@ -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;
@@ -362,14 +364,14 @@ bool QQmlDirParser::designerSupported() const
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
- const QString output = QString::fromLatin1("{%1 %2.%3}").
+ const QString output = QStringLiteral("{%1 %2.%3}").
arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
return debug << qPrintable(output);
}
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
{
- const QString output = QString::fromLatin1("{%1 %2.%3}").
+ const QString output = QStringLiteral("{%1 %2.%3}").
arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
return debug << qPrintable(output);
}
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index ffc890a2cf..9c5e48ae32 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -42,7 +42,6 @@
#include "qqmlexpression.h"
#include "qqmlcomponent.h"
#include "qqmlvme_p.h"
-#include <private/qqmlenginedebugservice_p.h>
#include "qqmlstringconverters_p.h"
#include "qqmlxmlhttprequest_p.h"
#include "qqmlscriptstring.h"
@@ -54,11 +53,7 @@
#include "qqmllist_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmlnotifier_p.h"
-#include <private/qqmldebugserver_p.h>
-#include <private/qqmlprofilerservice_p.h>
-#include <private/qv4debugservice_p.h>
-#include <private/qdebugmessageservice_p.h>
-#include <private/qqmlenginecontrolservice_p.h>
+#include <private/qqmldebugconnector_p.h>
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
#include <private/qqmlboundsignal_p.h>
@@ -225,7 +220,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 +241,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
*/
@@ -594,7 +592,7 @@ the same object as is returned from the Qt.include() call.
// Qt.include() is implemented in qv4include.cpp
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
-: propertyCapture(0), rootContext(0), isDebugging(false),
+: propertyCapture(0), rootContext(0),
profiler(0), outputWarningsToMsgLog(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
@@ -607,8 +605,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);
@@ -627,9 +625,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
@@ -666,6 +664,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);
@@ -799,7 +808,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);
}
}
@@ -824,14 +833,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;
@@ -861,15 +868,9 @@ void QQmlEnginePrivate::init()
rootContext = new QQmlContext(q,true);
- if (QCoreApplication::instance()->thread() == q->thread() &&
- QQmlEngineDebugService::isDebuggingEnabled()) {
- isDebugging = true;
- QQmlEngineDebugService::instance();
- QV4DebugService::instance();
- QQmlProfilerService::instance();
- QDebugMessageService::instance();
- QQmlEngineControlService::instance();
- QQmlDebugServer::instance()->addEngine(q);
+ if (QCoreApplication::instance()->thread() == q->thread() && QQmlDebugConnector::instance()) {
+ QQmlDebugConnector::instance()->open();
+ QQmlDebugConnector::instance()->addEngine(q);
}
}
@@ -886,7 +887,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
@@ -947,8 +947,9 @@ QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent)
QQmlEngine::~QQmlEngine()
{
Q_D(QQmlEngine);
- if (d->isDebugging)
- QQmlDebugServer::instance()->removeEngine(this);
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
+ if (server)
+ server->removeEngine(this);
d->typeLoader.invalidate();
@@ -1492,51 +1493,6 @@ Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *o
#endif // QT_DEPRECATED_SINCE(5, 1)
-QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
-{
-#ifndef QQML_NO_DEBUG_PROTOCOL
- if (!QQmlEnginePrivate::qml_debugging_enabled
- && printWarning) {
- qDebug("QML debugging is enabled. Only use this in a safe environment.");
- }
- QQmlEnginePrivate::qml_debugging_enabled = true;
-#else
- Q_UNUSED(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();
@@ -1678,12 +1634,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();
@@ -1696,9 +1651,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.
@@ -1710,7 +1665,7 @@ void QQmlData::destroyed(QObject *object)
if (location.sourceFile.isEmpty())
location.sourceFile = QStringLiteral("<Unknown File>");
locationString.append(location.sourceFile);
- locationString.append(QString::fromLatin1(":%0: ").arg(location.line));
+ locationString.append(QStringLiteral(":%0: ").arg(location.line));
QString source = expr->expression();
if (source.size() > 100) {
source.truncate(96);
@@ -1727,7 +1682,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;
@@ -2140,8 +2095,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;
@@ -2203,10 +2157,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) {
@@ -2223,7 +2177,6 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
overloadError = true;
}
}
-#endif
if (overloadError) {
if (hasCopied) raw->release();
@@ -2231,6 +2184,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);
@@ -2281,8 +2235,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);
@@ -2291,8 +2245,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);
@@ -2303,8 +2257,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);
@@ -2315,8 +2269,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);
@@ -2328,8 +2282,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..26ee3bd655 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,21 +123,11 @@ 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;
QQmlContext *rootContext;
- bool isDebugging;
QQmlProfiler *profiler;
void enableProfiler();
@@ -208,7 +198,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 +252,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 +336,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 +345,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 +404,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/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index d904242f93..aa2b4b6aee 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -62,40 +62,11 @@ const QMetaObject *QQmlValueTypeProvider::metaObjectForMetaType(int type)
return 0;
}
-bool QQmlValueTypeProvider::initValueType(int type, void *data, size_t n)
+bool QQmlValueTypeProvider::initValueType(int type, QVariant& dst)
{
- Q_ASSERT(data);
-
- QQmlValueTypeProvider *p = this;
- do {
- if (p->init(type, data, n))
- return true;
- } while ((p = p->next));
-
- return false;
-}
-
-bool QQmlValueTypeProvider::destroyValueType(int type, void *data, size_t n)
-{
- Q_ASSERT(data);
-
QQmlValueTypeProvider *p = this;
do {
- if (p->destroy(type, data, n))
- return true;
- } while ((p = p->next));
-
- return false;
-}
-
-bool QQmlValueTypeProvider::copyValueType(int type, const void *src, void *dst, size_t n)
-{
- Q_ASSERT(src);
- Q_ASSERT(dst);
-
- QQmlValueTypeProvider *p = this;
- do {
- if (p->copy(type, src, dst, n))
+ if (p->init(type, dst))
return true;
} while ((p = p->next));
@@ -188,14 +159,13 @@ QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle
return QVariant();
}
-bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const void *rhs, size_t rhsSize)
+bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const QVariant& rhs)
{
Q_ASSERT(lhs);
- Q_ASSERT(rhs);
QQmlValueTypeProvider *p = this;
do {
- if (p->equal(type, lhs, rhs, rhsSize))
+ if (p->equal(type, lhs, rhs))
return true;
} while ((p = p->next));
@@ -216,28 +186,26 @@ bool QQmlValueTypeProvider::storeValueType(int type, const void *src, void *dst,
return false;
}
-bool QQmlValueTypeProvider::readValueType(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+bool QQmlValueTypeProvider::readValueType(const QVariant& src, void *dst, int dstType)
{
- Q_ASSERT(src);
Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->read(srcType, src, srcSize, dstType, dst))
+ if (p->read(src, dst, dstType))
return true;
} while ((p = p->next));
return false;
}
-bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst, size_t n)
+bool QQmlValueTypeProvider::writeValueType(int type, const void *src, QVariant& dst)
{
Q_ASSERT(src);
- Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->write(type, src, dst, n))
+ if (p->write(type, src, dst))
return true;
} while ((p = p->next));
@@ -245,19 +213,17 @@ bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst,
}
const QMetaObject *QQmlValueTypeProvider::getMetaObjectForMetaType(int) { return 0; }
-bool QQmlValueTypeProvider::init(int, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::destroy(int, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::copy(int, const void *, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::init(int, QVariant&) { return false; }
bool QQmlValueTypeProvider::create(int, int, const void *[], QVariant *) { return false; }
bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_t) { return false; }
bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; }
bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *) { return false; }
-bool QQmlValueTypeProvider::equal(int, const void *, const void *, size_t) { return false; }
+bool QQmlValueTypeProvider::equal(int, const void *, const QVariant&) { return false; }
bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::read(int, const void *, size_t, int, void *) { return false; }
-bool QQmlValueTypeProvider::write(int, const void *, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::read(const QVariant&, void *, int) { return false; }
+bool QQmlValueTypeProvider::write(int, const void *, QVariant&) { return false; }
Q_GLOBAL_STATIC(QQmlValueTypeProvider, nullValueTypeProvider)
static QQmlValueTypeProvider *valueTypeProvider = 0;
@@ -359,7 +325,7 @@ QObject *QQmlGuiProvider::inputMethod()
{
// We don't have any input method code by default
QObject *o = new QObject();
- o->setObjectName(QString::fromLatin1("No inputMethod available"));
+ o->setObjectName(QStringLiteral("No inputMethod available"));
QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
return o;
}
@@ -368,7 +334,7 @@ QObject *QQmlGuiProvider::inputMethod()
QObject *QQmlGuiProvider::styleHints()
{
QObject *o = new QObject();
- o->setObjectName(QString::fromLatin1("No styleHints available"));
+ o->setObjectName(QStringLiteral("No styleHints available"));
QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
return o;
}
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 7856d85376..d09ae21f56 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -224,9 +224,7 @@ public:
const QMetaObject *metaObjectForMetaType(int);
- bool initValueType(int, void *, size_t);
- bool destroyValueType(int, void *, size_t);
- bool copyValueType(int, const void *, void *, size_t);
+ bool initValueType(int, QVariant&);
QVariant createValueType(int, int, const void *[]);
bool createValueFromString(int, const QString &, void *, size_t);
@@ -236,16 +234,14 @@ public:
QVariant createVariantFromString(int, const QString &, bool *);
QVariant createVariantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, bool*);
- bool equalValueType(int, const void *, const void *, size_t);
+ bool equalValueType(int, const void *, const QVariant&);
bool storeValueType(int, const void *, void *, size_t);
- bool readValueType(int, const void *, size_t, int, void *);
- bool writeValueType(int, const void *, void *, size_t);
+ bool readValueType(const QVariant&, void *, int);
+ bool writeValueType(int, const void *, QVariant&);
private:
virtual const QMetaObject *getMetaObjectForMetaType(int);
- virtual bool init(int, void *, size_t);
- virtual bool destroy(int, void *, size_t);
- virtual bool copy(int, const void *, void *, size_t);
+ virtual bool init(int, QVariant&);
virtual bool create(int, int, const void *[], QVariant *);
virtual bool createFromString(int, const QString &, void *, size_t);
@@ -255,10 +251,10 @@ private:
virtual bool variantFromString(int, const QString &, QVariant *);
virtual bool variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *);
- virtual bool equal(int, const void *, const void *, size_t);
+ virtual bool equal(int, const void *, const QVariant&);
virtual bool store(int, const void *, void *, size_t);
- virtual bool read(int, const void *, size_t, int, void *);
- virtual bool write(int, const void *, void *, size_t);
+ virtual bool read(const QVariant&, void *, int);
+ virtual bool write(int, const void *, QVariant&);
friend Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *);
friend Q_QML_PRIVATE_EXPORT void QQml_removeValueTypeProvider(QQmlValueTypeProvider *);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index ff48a10d95..b17bb0455d 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
};
/*!
@@ -382,7 +385,7 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const
// We need to exclude the entry for the current baseUrl. This can happen for example
// when handling qmldir files on the remote dir case and the current type is marked as
// singleton.
-bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QString baseUrl)
+bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QString &baseUrl)
{
if (importUrl.isEmpty())
return false;
@@ -398,7 +401,7 @@ bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QSt
return true;
}
-void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::CompositeSingletonReference> &resultList, QUrl baseUrl)
+void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::CompositeSingletonReference> &resultList, const QUrl &baseUrl)
{
typedef QQmlDirComponents::const_iterator ConstIterator;
@@ -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..967a7e75d7 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);
}
@@ -256,33 +287,77 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
}
}
-void QQmlJavaScriptExpression::clearError()
+void QQmlPropertyCapture::registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
{
- if (m_vtable.hasValue()) {
- m_vtable.value().clearError();
- m_vtable.value().removeError();
+ // Let the caller check and avoid the function call :)
+ Q_ASSERT(compiledFunction->hasQmlDependencies());
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ if (!ep)
+ return;
+ QQmlPropertyCapture *capture = ep->propertyCapture;
+ if (!capture)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext());
+ QQmlContextData *qmlContext = context->qmlContext();
+
+ const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
+ const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
+ for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
+ Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
+ capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
+ }
+
+ Q_ASSERT(qmlContext->contextObject);
+ const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
+ const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
+ for (int i = 0; i < contextPropertyDependencyCount; ++i) {
+ const int propertyIndex = *contextPropertyDependency++;
+ const int notifyIndex = *contextPropertyDependency++;
+ capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
+ }
+
+ QObject *scopeObject = context->qmlScope();
+ const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
+ const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
+ for (int i = 0; i < scopePropertyDependencyCount; ++i) {
+ const int propertyIndex = *scopePropertyDependency++;
+ const int notifyIndex = *scopePropertyDependency++;
+ capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
}
+
+}
+
+
+void QQmlJavaScriptExpression::clearError()
+{
+ 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 +383,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 +411,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 +428,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..f0a3741588 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,52 @@ 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);
+
+ static void registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
+
+ QQmlEngine *engine;
+ QQmlJavaScriptExpression *expression;
+ QQmlJavaScriptExpression::DeleteWatcher *watcher;
+ QFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> guards;
+ QStringList *errorString;
};
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
@@ -222,18 +229,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..d09f4df54c 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;
@@ -138,9 +138,9 @@ void QmlListWrapper::put(Managed *m, String *name, const Value &value)
Q_UNUSED(value);
}
-void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
Q_ASSERT(m->as<QmlListWrapper>());
QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 3590bcb1c9..ff006d4302 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,10 +81,10 @@ 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);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *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 cb8c2bd3b5..fbb21f4562 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -258,7 +258,7 @@ QObject *QQmlType::SingletonInstanceInfo::qobjectApi(QQmlEngine *e) const
return qobjectApis.value(e);
}
-void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, QJSValue v)
+void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, const QJSValue &v)
{
scriptApis.insert(e, v);
}
@@ -1110,7 +1110,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)
@@ -1440,8 +1442,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;
}
@@ -1718,7 +1720,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);
@@ -1752,7 +1754,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;
@@ -1823,8 +1825,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/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index e5ac20d314..61a6567f1d 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -191,7 +191,7 @@ public:
void setQObjectApi(QQmlEngine *, QObject *);
QObject *qobjectApi(QQmlEngine *) const;
- void setScriptApi(QQmlEngine *, QJSValue);
+ void setScriptApi(QQmlEngine *, const QJSValue &);
QJSValue scriptApi(QQmlEngine *) const;
void init(QQmlEngine *);
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index 2742bfc84b..90902c089d 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -63,9 +63,6 @@ class QQmlNotifierEndpoint
QQmlNotifierEndpoint *next;
QQmlNotifierEndpoint **prev;
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
@@ -77,7 +74,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);
@@ -90,6 +88,8 @@ public:
inline bool isNotifying() const;
inline void cancelNotify();
+ inline int signalIndex() const { return sourceSignal; }
+
private:
friend class QQmlData;
friend class QQmlNotifier;
@@ -135,8 +135,8 @@ void QQmlNotifier::notify()
if (endpoints) emitNotify(endpoints, args);
}
-QQmlNotifierEndpoint::QQmlNotifierEndpoint()
-: next(0), prev(0), senderPtr(0), callback(None), sourceSignal(-1)
+QQmlNotifierEndpoint::QQmlNotifierEndpoint(Callback callback)
+: next(0), prev(0), senderPtr(0), callback(callback), sourceSignal(-1)
{
}
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..16138508dd 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -35,6 +35,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmldata_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <private/qv8engine_p.h>
#include <qqmlengine.h>
#include <qdebug.h>
@@ -106,6 +107,28 @@ QMetaObject *QQmlOpenMetaObjectType::metaObject() const
return d->mem;
}
+void QQmlOpenMetaObjectType::createProperties(const QVector<QByteArray> &names)
+{
+ for (int i = 0; i < names.count(); ++i) {
+ const QByteArray &name = names.at(i);
+ const int id = d->mob.propertyCount();
+ d->mob.addSignal("__" + QByteArray::number(id) + "()");
+ QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
+ propertyCreated(id, build);
+ d->names.insert(name, id);
+ }
+ free(d->mem);
+ d->mem = d->mob.toMetaObject();
+ QSet<QQmlOpenMetaObject*>::iterator it = d->referers.begin();
+ while (it != d->referers.end()) {
+ QQmlOpenMetaObject *omo = *it;
+ *static_cast<QMetaObject *>(omo) = *d->mem;
+ if (d->cache)
+ d->cache->update(omo);
+ ++it;
+ }
+}
+
int QQmlOpenMetaObjectType::createProperty(const QByteArray &name)
{
int id = d->mob.propertyCount();
@@ -230,6 +253,14 @@ QQmlOpenMetaObjectType *QQmlOpenMetaObject::type() const
return d->type;
}
+void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(propertyName);
+ if (iter == d->type->d->names.constEnd())
+ return;
+ activate(d->object, *iter + d->type->d->signalOffset, 0);
+}
+
int QQmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
{
if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
@@ -277,8 +308,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 +317,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 +330,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;
@@ -337,7 +368,7 @@ void QQmlOpenMetaObject::setCached(bool c)
QQmlData *qmldata = QQmlData::get(d->object, true);
if (d->cacheProperties) {
if (!d->type->d->cache)
- d->type->d->cache = new QQmlPropertyCache(d->type->d->engine, this);
+ d->type->d->cache = new QQmlPropertyCache(QV8Engine::getV4(d->type->d->engine), this);
qmldata->propertyCache = d->type->d->cache;
d->type->d->cache->addref();
} else {
diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h
index 6a29d08d4e..75ce9addd6 100644
--- a/src/qml/qml/qqmlopenmetaobject_p.h
+++ b/src/qml/qml/qqmlopenmetaobject_p.h
@@ -54,6 +54,7 @@ public:
QQmlOpenMetaObjectType(const QMetaObject *base, QQmlEngine *engine);
~QQmlOpenMetaObjectType();
+ void createProperties(const QVector<QByteArray> &names);
int createProperty(const QByteArray &name);
int propertyOffset() const;
@@ -101,6 +102,8 @@ public:
QQmlOpenMetaObjectType *type() const;
+ void emitPropertyNotification(const QByteArray &propertyName);
+
protected:
virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
virtual int createProperty(const char *, const char *);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 800f650075..c1120b4542 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;
-
- 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;
- }
+ Q_ASSERT(binding);
- // 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);
- }
- }
+ QObject *object = binding->targetObject();
+ int index = binding->targetPropertyIndex();
- 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,166 +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 *const *)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)
{
QMetaType metaType(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 0018275b95..9a935ed55f 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>
@@ -231,10 +231,10 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
/*!
Creates a new empty QQmlPropertyCache.
*/
-QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
-: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e)
+ : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
+ _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
}
@@ -242,10 +242,10 @@ QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
/*!
Creates a new QQmlPropertyCache of \a metaObject.
*/
-QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e, const QMetaObject *metaObject)
-: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject *metaObject)
+ : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
+ _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
Q_ASSERT(metaObject);
@@ -818,7 +818,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
}
}
- data->flags |= flagsForPropertyType(data->propType, qobject_cast<QQmlEngine*>(engine));
+ data->flags |= flagsForPropertyType(data->propType, engine->qmlEngine());
}
data->flags &= ~QQmlPropertyData::NotFullyResolved;
@@ -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();
@@ -1135,7 +1134,7 @@ QString QQmlPropertyCache::signalParameterStringForJS(int index, QString *errorS
}
QString error;
- QString parameters = signalParameterStringForJS(QV8Engine::getV4(engine), parameterNameList, &error);
+ QString parameters = signalParameterStringForJS(engine, parameterNameList, &error);
A *arguments = static_cast<A *>(signalData->arguments);
arguments->signalParameterStringForJS = new QString(!error.isEmpty() ? error : parameters);
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 6ed9ec0d36..2ee399c496 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;
@@ -243,8 +243,8 @@ class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
{
public:
- QQmlPropertyCache(QJSEngine *);
- QQmlPropertyCache(QJSEngine *, const QMetaObject *);
+ QQmlPropertyCache(QV4::ExecutionEngine *);
+ QQmlPropertyCache(QV4::ExecutionEngine *, const QMetaObject *);
virtual ~QQmlPropertyCache();
void update(const QMetaObject *);
@@ -377,8 +377,10 @@ private:
_hasPropertyOverrides |= isOverride;
}
- QJSEngine *engine;
+public:
+ QV4::ExecutionEngine *engine;
+private:
QQmlPropertyCache *_parent;
int propertyIndexCacheStart;
int methodIndexCacheStart;
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 10eaae0c77..6a71a07e9b 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 97fc382c33..0ffeddbabc 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -51,8 +52,8 @@
QT_BEGIN_NAMESPACE
-QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr(bool isVar)
- : QQmlGuard<QObject>(0), m_target(0), m_isVar(isVar), m_index(-1)
+QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr()
+ : QQmlGuard<QObject>(0), m_target(0), m_index(-1)
{
}
@@ -63,14 +64,12 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr()
void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
{
if (m_target && m_index >= 0) {
- if (m_isVar && m_target->varPropertiesInitialized && !m_target->varProperties.isUndefined()) {
- // Set the var property to NULL
- QV4::ExecutionEngine *v4 = m_target->varProperties.engine();
+ if (m_target->propertiesInitialized && !m_target->properties.isUndefined()) {
+ QV4::ExecutionEngine *v4 = m_target->cache->engine;
if (v4) {
QV4::Scope scope(v4);
- QV4::ScopedArrayObject a(scope, m_target->varProperties.value());
- if (a)
- a->putIndexed(m_index - m_target->firstVarPropertyIndex, QV4::ScopedValue(scope, QV4::Primitive::nullValue()));
+ QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value());
+ *(sp->data() + m_index) = QV4::Primitive::nullValue();
}
}
@@ -86,545 +85,382 @@ void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *
setObject(obj);
}
-class QQmlVMEVariant
-{
-public:
- inline QQmlVMEVariant();
- inline ~QQmlVMEVariant();
-
- inline const void *dataPtr() const;
- inline void *dataPtr();
- inline int dataType() const;
- inline size_t dataSize() const;
-
- inline QObject *asQObject();
- inline const QVariant &asQVariant();
- inline int asInt();
- inline bool asBool();
- inline double asDouble();
- inline const QString &asQString();
- inline const QUrl &asQUrl();
- inline const QTime &asQTime();
- inline const QDate &asQDate();
- inline const QDateTime &asQDateTime();
- inline const QRectF &asQRectF();
- inline const QPointF &asQPointF();
- inline const QSizeF &asQSizeF();
- inline const QJSValue &asQJSValue();
-
- inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index);
- inline void setValue(const QVariant &);
- inline void setValue(int);
- inline void setValue(bool);
- inline void setValue(double);
- inline void setValue(const QString &);
- inline void setValue(const QUrl &);
- inline void setValue(const QTime &);
- inline void setValue(const QDate &);
- inline void setValue(const QDateTime &);
- inline void setValue(const QRectF &);
- inline void setValue(const QPointF &);
- inline void setValue(const QSizeF &);
- inline void setValue(const QJSValue &);
-
- inline void setDataType(int t);
-
- inline void ensureValueType(int);
-
-private:
- int type;
- void *data[8]; // Large enough to hold all types
-
- inline void cleanup();
-};
-
class QQmlVMEMetaObjectEndpoint : public QQmlNotifierEndpoint
{
public:
QQmlVMEMetaObjectEndpoint();
- static void vmecallback(QQmlNotifierEndpoint *, void **);
void tryConnect();
QFlagPointer<QQmlVMEMetaObject> metaObject;
};
-
-QQmlVMEVariant::QQmlVMEVariant()
-: type(QVariant::Invalid)
+QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint)
{
}
-QQmlVMEVariant::~QQmlVMEVariant()
+void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
{
- cleanup();
+ QQmlVMEMetaObjectEndpoint *vmee = static_cast<QQmlVMEMetaObjectEndpoint*>(e);
+ vmee->tryConnect();
}
-void QQmlVMEVariant::cleanup()
+void QQmlVMEMetaObjectEndpoint::tryConnect()
{
- if (type == QVariant::Invalid) {
- } else if (type == QMetaType::Int ||
- type == QMetaType::Bool ||
- type == QMetaType::Double) {
- type = QVariant::Invalid;
- } else if (type == QMetaType::QObjectStar) {
- ((QQmlVMEVariantQObjectPtr*)dataPtr())->~QQmlVMEVariantQObjectPtr();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QString) {
- ((QString *)dataPtr())->~QString();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QUrl) {
- ((QUrl *)dataPtr())->~QUrl();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QTime) {
- ((QTime *)dataPtr())->~QTime();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QDate) {
- ((QDate *)dataPtr())->~QDate();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QDateTime) {
- ((QDateTime *)dataPtr())->~QDateTime();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QRectF) {
- ((QRectF *)dataPtr())->~QRectF();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QPointF) {
- ((QPointF *)dataPtr())->~QPointF();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QSizeF) {
- ((QSizeF *)dataPtr())->~QSizeF();
- type = QVariant::Invalid;
- } else if (type == qMetaTypeId<QVariant>()) {
- ((QVariant *)dataPtr())->~QVariant();
- type = QVariant::Invalid;
- } else if (type == qMetaTypeId<QJSValue>()) {
- ((QJSValue *)dataPtr())->~QJSValue();
- type = QVariant::Invalid;
+ int aliasId = this - metaObject->aliasEndpoints;
+
+ if (metaObject.flag()) {
+ // This is actually notify
+ int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
+ metaObject->activate(metaObject->object, sigIdx, 0);
} else {
- if (QQml_valueTypeProvider()->destroyValueType(type, dataPtr(), dataSize())) {
- type = QVariant::Invalid;
+ QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
+ if (!d->isObjectAlias()) {
+ QQmlContextData *ctxt = metaObject->ctxt;
+ QObject *target = ctxt->idValues[d->contextIdx].data();
+ if (!target)
+ return;
+
+ if (d->notifySignal != -1)
+ connect(target, d->notifySignal, ctxt->engine);
}
+
+ metaObject.setFlag();
}
}
-int QQmlVMEVariant::dataType() const
+QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
{
- return type;
-}
+ if (!hasAssignedMetaObjectData) {
+ *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
-const void *QQmlVMEVariant::dataPtr() const
-{
- return &data;
-}
+ if (parent.isT1())
+ this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
+ else
+ this->d.superdata = parent.asT2();
-void *QQmlVMEVariant::dataPtr()
-{
- return &data;
-}
+ hasAssignedMetaObjectData = true;
+ }
-size_t QQmlVMEVariant::dataSize() const
-{
- return sizeof(data);
+ return this;
}
-QObject *QQmlVMEVariant::asQObject()
+QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
+ QQmlPropertyCache *cache,
+ const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData)
+: object(obj),
+ ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
+ hasAssignedMetaObjectData(false), aliasEndpoints(0),
+ propertiesInitialized(false), interceptors(0), methods(0)
{
- if (type != QMetaType::QObjectStar)
- setValue((QObject *)0, 0, -1);
-
- return *(QQmlGuard<QObject> *)(dataPtr());
-}
+ QObjectPrivate *op = QObjectPrivate::get(obj);
-const QVariant &QQmlVMEVariant::asQVariant()
-{
- if (type != QMetaType::QVariant)
- setValue(QVariant());
+ if (op->metaObject) {
+ parent = op->metaObject;
+ // Use the extra flag in QBiPointer to know if we can safely cast parent.asT1() to QQmlVMEMetaObject*
+ parent.setFlagValue(QQmlData::get(obj)->hasVMEMetaObject);
+ } else
+ parent = obj->metaObject();
- return *(QVariant *)(dataPtr());
-}
+ op->metaObject = this;
+ QQmlData::get(obj)->hasVMEMetaObject = true;
-int QQmlVMEVariant::asInt()
-{
- if (type != QMetaType::Int)
- setValue(int(0));
+ aConnected.resize(metaData->aliasCount);
+ int list_type = qMetaTypeId<QQmlListProperty<QObject> >();
+ int qobject_type = qMetaTypeId<QObject*>();
+ int variant_type = qMetaTypeId<QVariant>();
+ // Need JS wrapper to ensure properties are marked.
+ // ### FIXME: I hope that this can be removed once we have the proper scope chain
+ // set up and the JS wrappers always exist.
+ bool needsJSWrapper = (metaData->propertyCount > 0);
- return *(int *)(dataPtr());
-}
+ // ### Optimize
+ for (int ii = 0; ii < metaData->propertyCount; ++ii) {
+ int t = (metaData->propertyData() + ii)->propertyType;
+ if (t == list_type) {
+ listProperties.append(List(methodOffset() + ii, this));
+ writeProperty(ii, listProperties.count() - 1);
+ } else if (!needsJSWrapper && (t == qobject_type || t == variant_type)) {
+ needsJSWrapper = true;
+ }
+ }
-bool QQmlVMEVariant::asBool()
-{
- if (type != QMetaType::Bool)
- setValue(bool(false));
+ if (needsJSWrapper)
+ ensureQObjectWrapper();
- return *(bool *)(dataPtr());
-}
+ if (qmlBindingContext && metaData->methodCount) {
+ methods = new QV4::PersistentValue[metaData->methodCount];
-double QQmlVMEVariant::asDouble()
-{
- if (type != QMetaType::Double)
- setValue(double(0));
+ QV4::CompiledData::CompilationUnit *compilationUnit = compiledData->compilationUnit;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedObject o(scope);
+ for (int index = 0; index < metaData->methodCount; ++index) {
+ QQmlVMEMetaData::MethodData *data = metaData->methodData() + index;
- return *(double *)(dataPtr());
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex];
+ o = QV4::FunctionObject::createScriptFunction(qmlBindingContext, runtimeFunction);
+ methods[index].set(qmlBindingContext->engine(), o);
+ }
+ }
}
-const QString &QQmlVMEVariant::asQString()
+QQmlVMEMetaObject::~QQmlVMEMetaObject()
{
- if (type != QMetaType::QString)
- setValue(QString());
+ if (parent.isT1()) parent.asT1()->objectDestroyed(object);
+ delete [] aliasEndpoints;
+ delete [] methods;
- return *(QString *)(dataPtr());
+ qDeleteAll(varObjectGuards);
}
-const QUrl &QQmlVMEVariant::asQUrl()
+QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData()
{
- if (type != QMetaType::QUrl)
- setValue(QUrl());
+ if (!ensurePropertiesAllocated())
+ return 0;
- return *(QUrl *)(dataPtr());
+ return static_cast<QV4::MemberData*>(properties.asManaged());
}
-const QTime &QQmlVMEVariant::asQTime()
+void QQmlVMEMetaObject::writeProperty(int id, int v)
{
- if (type != QMetaType::QTime)
- setValue(QTime());
-
- return *(QTime *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromInt32(v);
}
-const QDate &QQmlVMEVariant::asQDate()
+void QQmlVMEMetaObject::writeProperty(int id, bool v)
{
- if (type != QMetaType::QDate)
- setValue(QDate());
-
- return *(QDate *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromBoolean(v);
}
-const QDateTime &QQmlVMEVariant::asQDateTime()
+void QQmlVMEMetaObject::writeProperty(int id, double v)
{
- if (type != QMetaType::QDateTime)
- setValue(QDateTime());
-
- return *(QDateTime *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromDouble(v);
}
-const QRectF &QQmlVMEVariant::asQRectF()
+void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
{
- if (type != QMetaType::QRectF)
- setValue(QRectF());
-
- return *(QRectF *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newString(v);
}
-const QSizeF &QQmlVMEVariant::asQSizeF()
+void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
{
- if (type != QMetaType::QSizeF)
- setValue(QSizeF());
-
- return *(QSizeF *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-const QPointF &QQmlVMEVariant::asQPointF()
+void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
{
- if (type != QMetaType::QPointF)
- setValue(QPointF());
-
- return *(QPointF *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-const QJSValue &QQmlVMEVariant::asQJSValue()
+void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
{
- if (type != qMetaTypeId<QJSValue>())
- setValue(QJSValue());
-
- return *(QJSValue *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(QObject *v, QQmlVMEMetaObject *target, int index)
+void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
{
- if (type != QMetaType::QObjectStar) {
- cleanup();
- type = QMetaType::QObjectStar;
- new (dataPtr()) QQmlVMEVariantQObjectPtr(false);
- }
- reinterpret_cast<QQmlVMEVariantQObjectPtr*>(dataPtr())->setGuardedValue(v, target, index);
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(const QVariant &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
{
- if (type != qMetaTypeId<QVariant>()) {
- cleanup();
- type = qMetaTypeId<QVariant>();
- new (dataPtr()) QVariant(v);
- } else {
- *(QVariant *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(int v)
+void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
{
- if (type != QMetaType::Int) {
- cleanup();
- type = QMetaType::Int;
- }
- *(int *)(dataPtr()) = v;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(bool v)
+void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
{
- if (type != QMetaType::Bool) {
- cleanup();
- type = QMetaType::Bool;
- }
- *(bool *)(dataPtr()) = v;
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
-void QQmlVMEVariant::setValue(double v)
-{
- if (type != QMetaType::Double) {
- cleanup();
- type = QMetaType::Double;
+ QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
+ if (v && !guard) {
+ guard = new QQmlVMEVariantQObjectPtr();
+ varObjectGuards.append(guard);
}
- *(double *)(dataPtr()) = v;
+ if (guard)
+ guard->setGuardedValue(v, this, id);
}
-void QQmlVMEVariant::setValue(const QString &v)
+int QQmlVMEMetaObject::readPropertyAsInt(int id)
{
- if (type != QMetaType::QString) {
- cleanup();
- type = QMetaType::QString;
- new (dataPtr()) QString(v);
- } else {
- *(QString *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0;
-void QQmlVMEVariant::setValue(const QUrl &v)
-{
- if (type != QMetaType::QUrl) {
- cleanup();
- type = QMetaType::QUrl;
- new (dataPtr()) QUrl(v);
- } else {
- *(QUrl *)(dataPtr()) = v;
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isInt32())
+ return 0;
+ return sv->integerValue();
}
-void QQmlVMEVariant::setValue(const QTime &v)
+bool QQmlVMEMetaObject::readPropertyAsBool(int id)
{
- if (type != QMetaType::QTime) {
- cleanup();
- type = QMetaType::QTime;
- new (dataPtr()) QTime(v);
- } else {
- *(QTime *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return false;
-void QQmlVMEVariant::setValue(const QDate &v)
-{
- if (type != QMetaType::QDate) {
- cleanup();
- type = QMetaType::QDate;
- new (dataPtr()) QDate(v);
- } else {
- *(QDate *)(dataPtr()) = v;
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isBoolean())
+ return false;
+ return sv->booleanValue();
}
-void QQmlVMEVariant::setValue(const QDateTime &v)
+double QQmlVMEMetaObject::readPropertyAsDouble(int id)
{
- if (type != QMetaType::QDateTime) {
- cleanup();
- type = QMetaType::QDateTime;
- new (dataPtr()) QDateTime(v);
- } else {
- *(QDateTime *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0.0;
-void QQmlVMEVariant::setValue(const QRectF &v)
-{
- if (type != QMetaType::QRectF) {
- cleanup();
- type = QMetaType::QRectF;
- new (dataPtr()) QRectF(v);
- } else {
- *(QRectF *)(dataPtr()) = v;
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isDouble())
+ return 0.0;
+ return sv->doubleValue();
}
-void QQmlVMEVariant::setValue(const QPointF &v)
+QString QQmlVMEMetaObject::readPropertyAsString(int id)
{
- if (type != QMetaType::QPointF) {
- cleanup();
- type = QMetaType::QPointF;
- new (dataPtr()) QPointF(v);
- } else {
- *(QPointF *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QString();
-void QQmlVMEVariant::setValue(const QSizeF &v)
-{
- if (type != QMetaType::QSizeF) {
- cleanup();
- type = QMetaType::QSizeF;
- new (dataPtr()) QSizeF(v);
- } else {
- *(QSizeF *)(dataPtr()) = v;
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isString())
+ return QString();
+ return sv->stringValue()->toQString();
}
-void QQmlVMEVariant::setValue(const QJSValue &v)
+QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
{
- if (type != qMetaTypeId<QJSValue>()) {
- cleanup();
- type = qMetaTypeId<QJSValue>();
- new (dataPtr()) QJSValue(v);
- } else {
- *(QJSValue *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QUrl();
-void QQmlVMEVariant::setDataType(int t)
-{
- type = t;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::Url)
+ return QUrl();
+ return v->d()->data.value<QUrl>();
}
-void QQmlVMEVariant::ensureValueType(int t)
+QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
{
- if (type != t) {
- cleanup();
- type = t;
- QQml_valueTypeProvider()->initValueType(t, dataPtr(), dataSize());
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QDate();
-QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
-{
- setCallback(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint);
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::Date)
+ return QDate();
+ return v->d()->data.value<QDate>();
}
-void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
+QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
{
- QQmlVMEMetaObjectEndpoint *vmee = static_cast<QQmlVMEMetaObjectEndpoint*>(e);
- vmee->tryConnect();
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QDateTime();
+
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::DateTime)
+ return QDateTime();
+ return v->d()->data.value<QDateTime>();
}
-void QQmlVMEMetaObjectEndpoint::tryConnect()
+QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
{
- int aliasId = this - metaObject->aliasEndpoints;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QSizeF();
- if (metaObject.flag()) {
- // This is actually notify
- int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
- metaObject->activate(metaObject->object, sigIdx, 0);
- } else {
- QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
- if (!d->isObjectAlias()) {
- QQmlContextData *ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValues[d->contextIdx].data();
- if (!target)
- return;
-
- if (d->notifySignal != -1)
- connect(target, d->notifySignal, ctxt->engine);
- }
-
- metaObject.setFlag();
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::SizeF)
+ return QSizeF();
+ return v->d()->data.value<QSizeF>();
}
-QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
+QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
{
- if (!hasAssignedMetaObjectData) {
- *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QPointF();
- if (parent.isT1())
- this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
- else
- this->d.superdata = parent.asT2();
-
- hasAssignedMetaObjectData = true;
- }
-
- return this;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::PointF)
+ return QPointF();
+ return v->d()->data.value<QPointF>();
}
-QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
- QQmlPropertyCache *cache,
- const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData)
-: object(obj),
- ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
- hasAssignedMetaObjectData(false), data(0), aliasEndpoints(0), firstVarPropertyIndex(-1),
- varPropertiesInitialized(false), interceptors(0), v8methods(0)
+QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
{
- QObjectPrivate *op = QObjectPrivate::get(obj);
-
- if (op->metaObject) {
- parent = op->metaObject;
- // Use the extra flag in QBiPointer to know if we can safely cast parent.asT1() to QQmlVMEMetaObject*
- parent.setFlagValue(QQmlData::get(obj)->hasVMEMetaObject);
- } else
- parent = obj->metaObject();
-
- op->metaObject = this;
- QQmlData::get(obj)->hasVMEMetaObject = true;
-
- data = new QQmlVMEVariant[metaData->propertyCount - metaData->varPropertyCount];
-
- aConnected.resize(metaData->aliasCount);
- int list_type = qMetaTypeId<QQmlListProperty<QObject> >();
- int qobject_type = qMetaTypeId<QObject*>();
- int variant_type = qMetaTypeId<QVariant>();
- // Need JS wrapper to ensure variant and var properties are marked.
- // ### FIXME: I hope that this can be removed once we have the proper scope chain
- // set up and the JS wrappers always exist.
- bool needsJSWrapper = (metaData->varPropertyCount > 0);
-
- // ### Optimize
- for (int ii = 0; ii < metaData->propertyCount - metaData->varPropertyCount; ++ii) {
- int t = (metaData->propertyData() + ii)->propertyType;
- if (t == list_type) {
- listProperties.append(List(methodOffset() + ii, this));
- data[ii].setValue(listProperties.count() - 1);
- } else if (!needsJSWrapper && (t == qobject_type || t == variant_type)) {
- needsJSWrapper = true;
- }
- }
-
- firstVarPropertyIndex = metaData->propertyCount - metaData->varPropertyCount;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0;
- if (needsJSWrapper)
- ensureQObjectWrapper();
-
- if (qmlBindingContext && metaData->methodCount) {
- v8methods = new QV4::PersistentValue[metaData->methodCount];
-
- QV4::CompiledData::CompilationUnit *compilationUnit = compiledData->compilationUnit;
- QV4::Scope scope(QQmlEnginePrivate::get(ctxt->engine)->v4engine());
- QV4::ScopedObject o(scope);
- for (int index = 0; index < metaData->methodCount; ++index) {
- QQmlVMEMetaData::MethodData *data = metaData->methodData() + index;
-
- QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex];
- o = QV4::FunctionObject::createScriptFunction(qmlBindingContext, runtimeFunction);
- v8methods[index].set(qmlBindingContext->engine(), o);
- }
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::QObjectWrapper *wrapper = sv->as<QV4::QObjectWrapper>();
+ if (!wrapper)
+ return 0;
+ return wrapper->object();
}
-QQmlVMEMetaObject::~QQmlVMEMetaObject()
+QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id)
{
- if (parent.isT1()) parent.asT1()->objectDestroyed(object);
- delete [] data;
- delete [] aliasEndpoints;
- delete [] v8methods;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QRectF();
- qDeleteAll(varObjectGuards);
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::RectF)
+ return QRectF();
+ return v->d()->data.value<QRectF>();
}
-int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
+int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void **a)
{
+ Q_ASSERT(o == object);
+ Q_UNUSED(o);
+
int id = _id;
if (c == QMetaObject::WriteProperty && interceptors &&
!(*reinterpret_cast<int*>(a[3]) & QQmlPropertyPrivate::BypassInterceptor)) {
@@ -708,8 +544,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
int t = (metaData->propertyData() + id)->propertyType;
bool needActivate = false;
- if (id >= firstVarPropertyIndex) {
- Q_ASSERT(t == QMetaType::QVariant);
+ if (t == QQmlVMEMetaData::VarPropertyType) {
// the context can be null if accessing var properties from cpp after re-parenting an item.
QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
QV8Engine *v8e = (ep == 0) ? 0 : ep->v8engine();
@@ -729,47 +564,54 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
if (c == QMetaObject::ReadProperty) {
switch(t) {
case QVariant::Int:
- *reinterpret_cast<int *>(a[0]) = data[id].asInt();
+ *reinterpret_cast<int *>(a[0]) = readPropertyAsInt(id);
break;
case QVariant::Bool:
- *reinterpret_cast<bool *>(a[0]) = data[id].asBool();
+ *reinterpret_cast<bool *>(a[0]) = readPropertyAsBool(id);
break;
case QVariant::Double:
- *reinterpret_cast<double *>(a[0]) = data[id].asDouble();
+ *reinterpret_cast<double *>(a[0]) = readPropertyAsDouble(id);
break;
case QVariant::String:
- *reinterpret_cast<QString *>(a[0]) = data[id].asQString();
+ *reinterpret_cast<QString *>(a[0]) = readPropertyAsString(id);
break;
case QVariant::Url:
- *reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
+ *reinterpret_cast<QUrl *>(a[0]) = readPropertyAsUrl(id);
break;
case QVariant::Date:
- *reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
+ *reinterpret_cast<QDate *>(a[0]) = readPropertyAsDate(id);
break;
case QVariant::DateTime:
- *reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
+ *reinterpret_cast<QDateTime *>(a[0]) = readPropertyAsDateTime(id);
break;
case QVariant::RectF:
- *reinterpret_cast<QRectF *>(a[0]) = data[id].asQRectF();
+ *reinterpret_cast<QRectF *>(a[0]) = readPropertyAsRectF(id);
break;
case QVariant::SizeF:
- *reinterpret_cast<QSizeF *>(a[0]) = data[id].asQSizeF();
+ *reinterpret_cast<QSizeF *>(a[0]) = readPropertyAsSizeF(id);
break;
case QVariant::PointF:
- *reinterpret_cast<QPointF *>(a[0]) = data[id].asQPointF();
+ *reinterpret_cast<QPointF *>(a[0]) = readPropertyAsPointF(id);
break;
case QMetaType::QObjectStar:
- *reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
+ *reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id);
break;
case QMetaType::QVariant:
*reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
break;
default:
- QQml_valueTypeProvider()->readValueType(data[id].dataType(), data[id].dataPtr(), data->dataSize(), t, a[0]);
+ {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (v)
+ QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t);
+ }
break;
}
+ }
if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
- int listIndex = data[id].asInt();
+ const int listIndex = readPropertyAsInt(id);
const List *list = &listProperties.at(listIndex);
*reinterpret_cast<QQmlListProperty<QObject> *>(a[0]) =
QQmlListProperty<QObject>(object, const_cast<List *>(list),
@@ -781,58 +623,67 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
switch(t) {
case QVariant::Int:
- needActivate = *reinterpret_cast<int *>(a[0]) != data[id].asInt();
- data[id].setValue(*reinterpret_cast<int *>(a[0]));
+ needActivate = *reinterpret_cast<int *>(a[0]) != readPropertyAsInt(id);
+ writeProperty(id, *reinterpret_cast<int *>(a[0]));
break;
case QVariant::Bool:
- needActivate = *reinterpret_cast<bool *>(a[0]) != data[id].asBool();
- data[id].setValue(*reinterpret_cast<bool *>(a[0]));
+ needActivate = *reinterpret_cast<bool *>(a[0]) != readPropertyAsBool(id);
+ writeProperty(id, *reinterpret_cast<bool *>(a[0]));
break;
case QVariant::Double:
- needActivate = *reinterpret_cast<double *>(a[0]) != data[id].asDouble();
- data[id].setValue(*reinterpret_cast<double *>(a[0]));
+ needActivate = *reinterpret_cast<double *>(a[0]) != readPropertyAsDouble(id);
+ writeProperty(id, *reinterpret_cast<double *>(a[0]));
break;
case QVariant::String:
- needActivate = *reinterpret_cast<QString *>(a[0]) != data[id].asQString();
- data[id].setValue(*reinterpret_cast<QString *>(a[0]));
+ needActivate = *reinterpret_cast<QString *>(a[0]) != readPropertyAsString(id);
+ writeProperty(id, *reinterpret_cast<QString *>(a[0]));
break;
case QVariant::Url:
- needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
- data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
+ needActivate = *reinterpret_cast<QUrl *>(a[0]) != readPropertyAsUrl(id);
+ writeProperty(id, *reinterpret_cast<QUrl *>(a[0]));
break;
case QVariant::Date:
- needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
- data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
+ needActivate = *reinterpret_cast<QDate *>(a[0]) != readPropertyAsDate(id);
+ writeProperty(id, *reinterpret_cast<QDate *>(a[0]));
break;
case QVariant::DateTime:
- needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
- data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
+ needActivate = *reinterpret_cast<QDateTime *>(a[0]) != readPropertyAsDateTime(id);
+ writeProperty(id, *reinterpret_cast<QDateTime *>(a[0]));
break;
case QVariant::RectF:
- needActivate = *reinterpret_cast<QRectF *>(a[0]) != data[id].asQRectF();
- data[id].setValue(*reinterpret_cast<QRectF *>(a[0]));
+ needActivate = *reinterpret_cast<QRectF *>(a[0]) != readPropertyAsRectF(id);
+ writeProperty(id, *reinterpret_cast<QRectF *>(a[0]));
break;
case QVariant::SizeF:
- needActivate = *reinterpret_cast<QSizeF *>(a[0]) != data[id].asQSizeF();
- data[id].setValue(*reinterpret_cast<QSizeF *>(a[0]));
+ needActivate = *reinterpret_cast<QSizeF *>(a[0]) != readPropertyAsSizeF(id);
+ writeProperty(id, *reinterpret_cast<QSizeF *>(a[0]));
break;
case QVariant::PointF:
- needActivate = *reinterpret_cast<QPointF *>(a[0]) != data[id].asQPointF();
- data[id].setValue(*reinterpret_cast<QPointF *>(a[0]));
+ needActivate = *reinterpret_cast<QPointF *>(a[0]) != readPropertyAsPointF(id);
+ writeProperty(id, *reinterpret_cast<QPointF *>(a[0]));
break;
case QMetaType::QObjectStar:
- needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
- data[id].setValue(*reinterpret_cast<QObject **>(a[0]), this, id);
+ needActivate = *reinterpret_cast<QObject **>(a[0]) != readPropertyAsQObject(id);
+ writeProperty(id, *reinterpret_cast<QObject **>(a[0]));
break;
case QMetaType::QVariant:
writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
break;
- default:
- data[id].ensureValueType(t);
- needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
- QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
+ default: {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (!v) {
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant());
+ v = (md->data() + id)->as<QV4::VariantObject>();
+ }
+ QQml_valueTypeProvider()->initValueType(t, v->d()->data);
+ needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], v->d()->data);
+ QQml_valueTypeProvider()->writeValueType(t, a[0], v->d()->data);
+ }
break;
}
+ }
}
}
@@ -874,10 +725,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);
}
}
@@ -978,126 +827,122 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
return QV4::Primitive::undefinedValue().asReturnedValue();
}
- if (!v8methods)
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ if (!methods)
+ methods = new QV4::PersistentValue[metaData->methodCount];
- return v8methods[index].value();
+ return methods[index].value();
}
QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id)
{
- Q_ASSERT(id >= firstVarPropertyIndex);
+ Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
- if (ensureVarPropertiesAllocated()) {
- QV4::Scope scope(varProperties.engine());
- QV4::ScopedObject o(scope, varProperties.value());
- return o->getIndexed(id - firstVarPropertyIndex);
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ return (md->data() + id)->asReturnedValue();
return QV4::Primitive::undefinedValue().asReturnedValue();
}
QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
{
- if (id >= firstVarPropertyIndex) {
- if (ensureVarPropertiesAllocated()) {
- QV4::ExecutionEngine *v4 = varProperties.engine();
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, varProperties.value());
- QV4::ScopedValue val(scope, o->getIndexed(id - firstVarPropertyIndex));
- return scope.engine->toVariant(val, -1);
- }
- return QVariant();
- } else {
- if (data[id].dataType() == QMetaType::QObjectStar) {
- return QVariant::fromValue(data[id].asQObject());
- } else {
- return data[id].asQVariant();
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ const QV4::QObjectWrapper *wrapper = (md->data() + id)->as<QV4::QObjectWrapper>();
+ if (wrapper)
+ return QVariant::fromValue(wrapper->object());
+ const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (v)
+ return v->d()->data;
+ return cache->engine->toVariant(*(md->data() + id), -1);
}
+ return QVariant();
}
void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
{
- Q_ASSERT(id >= firstVarPropertyIndex);
- if (!ensureVarPropertiesAllocated())
+ Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
+
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
return;
- QV4::Scope scope(varProperties.engine());
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::ScopedObject vp(scope, varProperties.value());
- QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex));
- if (!!oldv)
- oldv->removeVmePropertyReference();
+ QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>();
+ if (oldVariant)
+ oldVariant->removeVmePropertyReference();
QObject *valueObject = 0;
QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
- QV4::ScopedObject o(scope, value);
- if (o) {
- // And, if the new value is a scarce resource, we need to ensure that it does not get
- // automatically released by the engine until no other references to it exist.
- if (QV4::VariantObject *v = o->as<QV4::VariantObject>()) {
- v->addVmePropertyReference();
- } else if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
- // We need to track this QObject to signal its deletion
- valueObject = wrapper->object();
-
- // Do we already have a QObject guard for this property?
- if (valueObject && !guard) {
- guard = new QQmlVMEVariantQObjectPtr(true);
- varObjectGuards.append(guard);
- }
+ // And, if the new value is a scarce resource, we need to ensure that it does not get
+ // automatically released by the engine until no other references to it exist.
+ if (QV4::VariantObject *v = const_cast<QV4::VariantObject*>(value.as<QV4::VariantObject>())) {
+ v->addVmePropertyReference();
+ } else if (QV4::QObjectWrapper *wrapper = const_cast<QV4::QObjectWrapper*>(value.as<QV4::QObjectWrapper>())) {
+ // We need to track this QObject to signal its deletion
+ valueObject = wrapper->object();
+
+ // Do we already have a QObject guard for this property?
+ if (valueObject && !guard) {
+ guard = new QQmlVMEVariantQObjectPtr();
+ varObjectGuards.append(guard);
}
}
- if (guard) {
+ if (guard)
guard->setGuardedValue(valueObject, this, id);
- }
// Write the value and emit change signal as appropriate.
- vp->putIndexed(id - firstVarPropertyIndex, value);
+ *(md->data() + id) = value;
activate(object, methodOffset() + id, 0);
}
void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
{
- if (id >= firstVarPropertyIndex) {
- if (!ensureVarPropertiesAllocated())
+ if ((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType) {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
return;
- QV4::Scope scope(varProperties.engine());
-
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::ScopedObject vp(scope, varProperties.value());
- QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex));
- if (!!oldv)
+ QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>();
+ if (oldv)
oldv->removeVmePropertyReference();
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
- QV4::ScopedValue newv(scope, scope.engine->fromVariant(value));
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue newv(scope, cache->engine->fromVariant(value));
QV4::Scoped<QV4::VariantObject> v(scope, newv);
if (!!v)
v->addVmePropertyReference();
// Write the value and emit change signal as appropriate.
QVariant currentValue = readPropertyAsVariant(id);
- vp->putIndexed(id - firstVarPropertyIndex, newv);
+ *(md->data() + id) = newv;
if ((currentValue.userType() != value.userType() || currentValue != value))
activate(object, methodOffset() + id, 0);
} else {
bool needActivate = false;
if (value.userType() == QMetaType::QObjectStar) {
QObject *o = *(QObject *const *)value.data();
- needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o);
- data[id].setValue(o, this, id);
+ needActivate = readPropertyAsQObject(id) != o; // TODO: still correct?
+ writeProperty(id, o);
} else {
- needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() ||
- data[id].asQVariant().userType() != value.userType() ||
- data[id].asQVariant() != value);
- data[id].setValue(value);
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ needActivate = (!v ||
+ v->d()->data.userType() != value.userType() ||
+ v->d()->data != value);
+ if (v)
+ v->removeVmePropertyReference();
+ *(md->data() + id) = cache->engine->newVariantObject(value);
+ v = static_cast<QV4::VariantObject *>(md->data() + id);
+ v->addVmePropertyReference();
+ }
}
if (needActivate)
@@ -1179,11 +1024,11 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
- if (!v8methods)
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ if (!methods)
+ methods = new QV4::PersistentValue[metaData->methodCount];
int methodIndex = index - methodOffset() - plainSignals;
- v8methods[methodIndex].set(function.asObject()->engine(), function);
+ methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
@@ -1205,57 +1050,47 @@ void QQmlVMEMetaObject::setVMEProperty(int index, const QV4::Value &v)
return writeVarProperty(index - propOffset(), v);
}
-bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
+bool QQmlVMEMetaObject::ensurePropertiesAllocated()
{
- if (!varPropertiesInitialized)
- allocateVarPropertiesArray();
+ if (!propertiesInitialized)
+ allocateProperties();
// in some situations, the QObject's v8object (and associated v8 data,
// such as the varProperties array) will have been cleaned up, but the
// QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
// In this situation, the varProperties handle will be (and should remain)
// empty.
- return !varProperties.isUndefined();
+ return !properties.isUndefined();
}
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(cache && cache->engine);
+ QV4::ExecutionEngine *v4 = cache->engine;
QV4::QObjectWrapper::wrap(v4, object);
}
void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
{
- QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
- QV4::ExecutionEngine *v4 = (ep == 0) ? 0 : ep->v4engine();
+ QV4::ExecutionEngine *v4 = cache ? cache->engine : 0;
if (v4 != e)
return;
- varProperties.markOnce(e);
-
- // add references created by VMEVariant properties
- int maxDataIdx = metaData->propertyCount - metaData->varPropertyCount;
- for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimize?
- if (data[ii].dataType() == QMetaType::QObjectStar) {
- // possible QObject reference.
- if (QObject *ref = data[ii].asQObject())
- QV4::QObjectWrapper::markWrapper(ref, e);
- }
- }
+ properties.markOnce(e);
if (QQmlVMEMetaObject *parent = parentVMEMetaObject())
parent->mark(e);
}
-void QQmlVMEMetaObject::allocateVarPropertiesArray()
+void QQmlVMEMetaObject::allocateProperties()
{
- QQmlEngine *qml = qmlEngine(object);
- assert(qml);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(qml->handle());
- QV4::Scope scope(v4);
- varProperties.set(scope.engine, v4->newArrayObject(metaData->varPropertyCount));
- varPropertiesInitialized = true;
+ Q_ASSERT(cache && cache->engine);
+ QV4::ExecutionEngine *v4 = cache->engine;
+ QV4::Heap::MemberData *data = QV4::MemberData::reallocate(v4, 0, metaData->propertyCount);
+ properties.set(v4, data);
+ for (uint i = 0; i < data->size; ++i)
+ data->data[i] = QV4::Encode::undefined();
+ propertiesInitialized = true;
}
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index f3048d426a..427e751f5d 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -63,7 +64,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
@@ -71,7 +72,6 @@ QT_BEGIN_NAMESPACE
struct QQmlVMEMetaData
{
- short varPropertyCount;
short propertyCount;
short aliasCount;
short signalCount;
@@ -108,6 +108,10 @@ struct QQmlVMEMetaData
}
};
+ enum {
+ VarPropertyType = -1
+ };
+
struct PropertyData {
int propertyType;
};
@@ -135,15 +139,14 @@ class QQmlVMEMetaObject;
class QQmlVMEVariantQObjectPtr : public QQmlGuard<QObject>
{
public:
- inline QQmlVMEVariantQObjectPtr(bool isVar);
+ inline QQmlVMEVariantQObjectPtr();
inline ~QQmlVMEVariantQObjectPtr();
inline void objectDestroyed(QObject *);
inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index);
QQmlVMEMetaObject *m_target;
- unsigned m_isVar : 1;
- int m_index : 31;
+ int m_index;
};
class QQmlVMEVariant;
@@ -177,7 +180,7 @@ public:
static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex);
protected:
- virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
public:
friend class QQmlVMEMetaObjectEndpoint;
@@ -195,14 +198,37 @@ public:
inline int signalCount() const;
bool hasAssignedMetaObjectData;
- QQmlVMEVariant *data;
QQmlVMEMetaObjectEndpoint *aliasEndpoints;
- QV4::WeakValue varProperties;
- int firstVarPropertyIndex;
- bool varPropertiesInitialized;
- inline void allocateVarPropertiesArray();
- inline bool ensureVarPropertiesAllocated();
+ QV4::WeakValue properties;
+ bool propertiesInitialized;
+ inline void allocateProperties();
+ inline bool ensurePropertiesAllocated();
+ QV4::MemberData *propertiesAsMemberData();
+
+ int readPropertyAsInt(int id);
+ bool readPropertyAsBool(int id);
+ double readPropertyAsDouble(int id);
+ QString readPropertyAsString(int id);
+ QSizeF readPropertyAsSizeF(int id);
+ QPointF readPropertyAsPointF(int id);
+ QUrl readPropertyAsUrl(int id);
+ QDate readPropertyAsDate(int id);
+ QDateTime readPropertyAsDateTime(int id);
+ QRectF readPropertyAsRectF(int id);
+ QObject* readPropertyAsQObject(int id);
+
+ void writeProperty(int id, int v);
+ void writeProperty(int id, bool v);
+ void writeProperty(int id, double v);
+ void writeProperty(int id, const QString& v);
+ void writeProperty(int id, const QPointF& v);
+ void writeProperty(int id, const QSizeF& v);
+ void writeProperty(int id, const QUrl& v);
+ void writeProperty(int id, const QDate& v);
+ void writeProperty(int id, const QDateTime& v);
+ void writeProperty(int id, const QRectF& v);
+ void writeProperty(int id, QObject *v);
void ensureQObjectWrapper();
@@ -213,7 +239,7 @@ public:
QQmlPropertyValueInterceptor *interceptors;
- QV4::PersistentValue *v8methods;
+ QV4::PersistentValue *methods;
QV4::ReturnedValue method(int);
QV4::ReturnedValue readVarProperty(int);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 2a3ede6a22..0870e2b2c5 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;
@@ -94,16 +95,6 @@ static inline QQmlXMLHttpRequestData *xhrdata(ExecutionEngine *v4)
return (QQmlXMLHttpRequestData *)v4->v8Engine->xmlHttpRequestData();
}
-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));
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))), v);
- return meObj.asReturnedValue();
-}
-
QQmlXMLHttpRequestData::QQmlXMLHttpRequestData()
{
}
@@ -222,8 +213,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 +235,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 *);
@@ -273,6 +264,7 @@ public:
static ReturnedValue method_get_nodeName(CallContext *ctx);
static ReturnedValue method_get_nodeValue(CallContext *ctx);
static ReturnedValue method_get_nodeType(CallContext *ctx);
+ static ReturnedValue method_get_namespaceUri(CallContext *ctx);
static ReturnedValue method_get_parentNode(CallContext *ctx);
static ReturnedValue method_get_childNodes(CallContext *ctx);
@@ -302,6 +294,7 @@ Heap::NodePrototype::NodePrototype(ExecutionEngine *engine)
o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, 0);
o->defineAccessorProperty(QStringLiteral("nodeValue"), QV4::NodePrototype::method_get_nodeValue, 0);
o->defineAccessorProperty(QStringLiteral("nodeType"), QV4::NodePrototype::method_get_nodeType, 0);
+ o->defineAccessorProperty(QStringLiteral("namespaceUri"), QV4::NodePrototype::method_get_namespaceUri, 0);
o->defineAccessorProperty(QStringLiteral("parentNode"), QV4::NodePrototype::method_get_parentNode, 0);
o->defineAccessorProperty(QStringLiteral("childNodes"), QV4::NodePrototype::method_get_childNodes, 0);
@@ -470,6 +463,16 @@ ReturnedValue NodePrototype::method_get_nodeType(CallContext *ctx)
return Encode(r->d()->d->type);
}
+ReturnedValue NodePrototype::method_get_namespaceUri(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ if (!r)
+ return ctx->engine()->throwTypeError();
+
+ return Encode(ctx->d()->engine->newString(r->d()->d->namespaceUri));
+}
+
ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx)
{
Scope scope(ctx);
@@ -871,10 +874,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 +890,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 +919,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 +935,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);
}
@@ -1002,7 +1005,7 @@ public:
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
- QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager);
+ QQmlXMLHttpRequest(QNetworkAccessManager *manager);
virtual ~QQmlXMLHttpRequest();
bool sendFlag() const;
@@ -1011,21 +1014,23 @@ public:
int replyStatus() const;
QString replyStatusText() const;
- ReturnedValue open(const Value &me, const QString &, const QUrl &, LoadType);
- ReturnedValue send(const Value &me, const QByteArray &);
- ReturnedValue abort(const Value &me);
+ ReturnedValue open(Object *thisObject, QQmlContextData *context, const QString &, const QUrl &, LoadType);
+ ReturnedValue send(Object *thisObject, QQmlContextData *context, const QByteArray &);
+ ReturnedValue abort(Object *thisObject, QQmlContextData *context);
void addHeader(const QString &, const QString &);
QString header(const QString &name);
QString headers();
-
QString responseBody();
const QByteArray & rawResponseBody() const;
bool receivedXml() const;
const QString & responseType() const;
void setResponseType(const QString &);
+
+ QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*);
+ QV4::ReturnedValue xmlResponseBody(QV4::ExecutionEngine*);
private slots:
void readyRead();
void error(QNetworkReply::NetworkError);
@@ -1034,7 +1039,6 @@ private slots:
private:
void requestFromUrl(const QUrl &url);
- ExecutionEngine *v4;
State m_state;
bool m_errorFlag;
bool m_sendFlag;
@@ -1058,12 +1062,11 @@ private:
#endif
void readEncoding();
- ReturnedValue getMe() const;
- void setMe(const Value &me);
- PersistentValue m_me;
+ PersistentValue m_thisObject;
+ QQmlGuardedContextData m_qmlContext;
- void dispatchCallbackImpl(const Value &me);
- void dispatchCallback(const Value &me);
+ static void dispatchCallback(Object *thisObj, QQmlContextData *context);
+ void dispatchCallback();
int m_status;
QString m_statusText;
@@ -1076,13 +1079,14 @@ private:
QNetworkAccessManager *networkAccessManager() { return m_nam; }
QString m_responseType;
+ QV4::PersistentValue m_parsedDocument;
};
-QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager)
- : v4(engine)
- , m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
+QQmlXMLHttpRequest::QQmlXMLHttpRequest(QNetworkAccessManager *manager)
+ : 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_parsedDocument()
{
}
@@ -1116,7 +1120,7 @@ QString QQmlXMLHttpRequest::replyStatusText() const
return m_statusText;
}
-ReturnedValue QQmlXMLHttpRequest::open(const Value &me, const QString &method, const QUrl &url, LoadType loadType)
+ReturnedValue QQmlXMLHttpRequest::open(Object *thisObject, QQmlContextData *context, const QString &method, const QUrl &url, LoadType loadType)
{
destroyNetwork();
m_sendFlag = false;
@@ -1127,7 +1131,7 @@ ReturnedValue QQmlXMLHttpRequest::open(const Value &me, const QString &method, c
m_request.setAttribute(QNetworkRequest::SynchronousRequestAttribute, loadType == SynchronousLoad);
m_state = Opened;
m_addedHeaders.clear();
- dispatchCallback(me);
+ dispatchCallback(thisObject, context);
return Encode::undefined();
}
@@ -1233,11 +1237,12 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
m_network = networkAccessManager()->put(request, m_data);
} else if (m_method == QLatin1String("DELETE")) {
m_network = networkAccessManager()->deleteResource(request);
- } else if (m_method == QLatin1String("OPTIONS")) {
+ } else if ((m_method == QLatin1String("OPTIONS")) ||
+ m_method == QLatin1String("PROPFIND")) {
QBuffer *buffer = new QBuffer;
buffer->setData(m_data);
buffer->open(QIODevice::ReadOnly);
- m_network = networkAccessManager()->sendCustomRequest(request, QByteArrayLiteral("OPTIONS"), buffer);
+ m_network = networkAccessManager()->sendCustomRequest(request, QByteArray(m_method.toUtf8().constData()), buffer);
buffer->setParent(m_network);
}
@@ -1261,21 +1266,22 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
}
}
-ReturnedValue QQmlXMLHttpRequest::send(const Value &me, const QByteArray &data)
+ReturnedValue QQmlXMLHttpRequest::send(Object *thisObject, QQmlContextData *context, const QByteArray &data)
{
m_errorFlag = false;
m_sendFlag = true;
m_redirectCount = 0;
m_data = data;
- setMe(me);
+ m_thisObject = thisObject;
+ m_qmlContext = context;
requestFromUrl(m_url);
return Encode::undefined();
}
-ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
+ReturnedValue QQmlXMLHttpRequest::abort(Object *thisObject, QQmlContextData *context)
{
destroyNetwork();
m_responseEntityBody = QByteArray();
@@ -1288,7 +1294,7 @@ ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
m_state = Done;
m_sendFlag = false;
- dispatchCallback(me);
+ dispatchCallback(thisObject, context);
}
m_state = Unsent;
@@ -1296,16 +1302,6 @@ ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
return Encode::undefined();
}
-ReturnedValue QQmlXMLHttpRequest::getMe() const
-{
- return m_me.value();
-}
-
-void QQmlXMLHttpRequest::setMe(const Value &me)
-{
- m_me.set(v4, me);
-}
-
void QQmlXMLHttpRequest::readyRead()
{
m_status =
@@ -1313,14 +1309,11 @@ void QQmlXMLHttpRequest::readyRead()
m_statusText =
QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
- Scope scope(v4);
- ScopedValue me(scope, m_me.value());
-
// ### We assume if this is called the headers are now available
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- dispatchCallback(me);
+ dispatchCallback();
}
bool wasEmpty = m_responseEntityBody.isEmpty();
@@ -1328,7 +1321,7 @@ void QQmlXMLHttpRequest::readyRead()
if (wasEmpty && !m_responseEntityBody.isEmpty())
m_state = Loading;
- dispatchCallback(me);
+ dispatchCallback();
}
static const char *errorToString(QNetworkReply::NetworkError error)
@@ -1359,9 +1352,6 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
qWarning().nospace() << " " << error << ' ' << errorToString(error) << ' ' << m_statusText;
}
- Scope scope(v4);
- ScopedValue me(scope, m_me.value());
-
if (error == QNetworkReply::ContentAccessDenied ||
error == QNetworkReply::ContentOperationNotPermittedError ||
error == QNetworkReply::ContentNotFoundError ||
@@ -1370,15 +1360,14 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
error == QNetworkReply::UnknownContentError ||
error == QNetworkReply::ProtocolInvalidOperationError) {
m_state = Loading;
- dispatchCallback(me);
+ dispatchCallback();
} else {
m_errorFlag = true;
m_responseEntityBody = QByteArray();
}
m_state = Done;
-
- dispatchCallback(me);
+ dispatchCallback();
}
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
@@ -1410,7 +1399,7 @@ void QQmlXMLHttpRequest::finished()
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
}
m_responseEntityBody.append(m_network->readAll());
readEncoding();
@@ -1427,15 +1416,14 @@ void QQmlXMLHttpRequest::finished()
destroyNetwork();
if (m_state < Loading) {
m_state = Loading;
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
}
m_state = Done;
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
- Scope scope(v4);
- ScopedValue v(scope, Primitive::undefinedValue());
- setMe(v);
+ m_thisObject.clear();
+ m_qmlContext.setContextData(0);
}
@@ -1478,6 +1466,32 @@ void QQmlXMLHttpRequest::setResponseType(const QString &responseType)
m_responseType = responseType;
}
+QV4::ReturnedValue QQmlXMLHttpRequest::jsonResponseBody(QV4::ExecutionEngine* engine)
+{
+ if (m_parsedDocument.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_parsedDocument.set(scope.engine, jsonObject);
+ }
+
+ return m_parsedDocument.value();
+}
+
+QV4::ReturnedValue QQmlXMLHttpRequest::xmlResponseBody(QV4::ExecutionEngine* engine)
+{
+ if (m_parsedDocument.isEmpty()) {
+ m_parsedDocument.set(engine, Document::load(engine, rawResponseBody()));
+ }
+
+ return m_parsedDocument.value();
+}
#ifndef QT_NO_TEXTCODEC
QTextCodec* QQmlXMLHttpRequest::findTextCodec() const
@@ -1523,57 +1537,38 @@ const QByteArray &QQmlXMLHttpRequest::rawResponseBody() const
return m_responseEntityBody;
}
-void QQmlXMLHttpRequest::dispatchCallbackImpl(const Value &me)
+void QQmlXMLHttpRequest::dispatchCallback(Object *thisObj, QQmlContextData *context)
{
- QV4::Scope scope(v4);
- ScopedObject o(scope, me);
- if (!o) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
- return;
- }
+ Q_ASSERT(thisObj);
- ScopedString s(scope, v4->newString(QStringLiteral("ThisObject")));
- ScopedObject thisObj(scope, o->get(s));
- if (!thisObj) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
+ if (!context)
+ // if the calling context object is no longer valid, then it has been
+ // deleted explicitly (e.g., by a Loader deleting the itemContext when
+ // the source is changed). We do nothing in this case, as the evaluation
+ // cannot succeed.
return;
- }
- s = v4->newString(QStringLiteral("onreadystatechange"));
+ QV4::Scope scope(thisObj->engine());
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("onreadystatechange")));
ScopedFunctionObject callback(scope, thisObj->get(s));
if (!callback) {
// not an error, but no onreadystatechange function to call.
return;
}
- s = v4->newString(QStringLiteral("ActivationObject"));
- ScopedObject activationObject(scope, o->get(s));
- if (!activationObject) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject"));
- return;
- }
+ QV4::ScopedCallData callData(scope);
+ callData->thisObject = Encode::undefined();
+ callback->call(callData);
- QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject);
- if (callingContext) {
- QV4::ScopedCallData callData(scope);
- callData->thisObject = activationObject.asReturnedValue();
- callback->call(callData);
+ if (scope.engine->hasException) {
+ QQmlError error = scope.engine->catchExceptionAsQmlError();
+ QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error);
}
-
- // if the callingContext object is no longer valid, then it has been
- // deleted explicitly (e.g., by a Loader deleting the itemContext when
- // the source is changed). We do nothing in this case, as the evaluation
- // cannot succeed.
-
}
-void QQmlXMLHttpRequest::dispatchCallback(const Value &me)
+void QQmlXMLHttpRequest::dispatchCallback()
{
- dispatchCallbackImpl(me);
- if (v4->hasException) {
- QQmlError error = v4->catchExceptionAsQmlError();
- QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v4->qmlEngine()), error);
- }
+ dispatchCallback(m_thisObject.as<Object>(), m_qmlContext.contextData());
}
void QQmlXMLHttpRequest::destroyNetwork()
@@ -1599,7 +1594,7 @@ struct QQmlXMLHttpRequestWrapper : Object {
struct QQmlXMLHttpRequestCtor : FunctionObject {
QQmlXMLHttpRequestCtor(ExecutionEngine *engine);
- Object *proto;
+ Pointer<Object> proto;
};
}
@@ -1625,21 +1620,21 @@ 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();
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine, scope.engine->v8Engine->networkAccessManager());
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager());
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->alloc<QQmlXMLHttpRequestWrapper>(scope.engine, r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototype(proto);
return w.asReturnedValue();
}
- static ReturnedValue call(Managed *, QV4::CallData *) {
+ static ReturnedValue call(const Managed *, QV4::CallData *) {
return Primitive::undefinedValue().asReturnedValue();
}
@@ -1679,7 +1674,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));
}
@@ -1739,14 +1734,15 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
method != QLatin1String("HEAD") &&
method != QLatin1String("POST") &&
method != QLatin1String("DELETE") &&
- method != QLatin1String("OPTIONS"))
+ method != QLatin1String("OPTIONS") &&
+ method != QLatin1String("PROPFIND"))
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
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)
@@ -1768,8 +1764,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->open(meObject, method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
+ return r->open(w, scope.engine->callingQmlContext(), method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
@@ -1835,8 +1830,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx)
if (ctx->argc() > 0)
data = ctx->args()[0].toQStringNoThrow().toUtf8();
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->send(meObject, data);
+ return r->send(w, scope.engine->callingQmlContext(), data);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
@@ -1847,8 +1841,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->abort(meObject);
+ return r->abort(w, scope.engine->callingQmlContext());
}
ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
@@ -1965,7 +1958,9 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
r->readyState() != QQmlXMLHttpRequest::Done)) {
return Encode::null();
} else {
- return Document::load(scope.engine, r->rawResponseBody());
+ if (r->responseType().isEmpty())
+ r->setResponseType(QLatin1String("document"));
+ return r->xmlResponseBody(scope.engine);
}
}
@@ -1986,6 +1981,10 @@ 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 if (responseType.compare(QLatin1String("document"), Qt::CaseInsensitive) == 0) {
+ return r->xmlResponseBody(scope.engine);
} else {
return QV4::Encode(scope.engine->newString(QString()));
}
@@ -2033,7 +2032,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..ce86fd3923 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -41,7 +41,8 @@
#include <private/qv8engine_p.h>
#include <QFileInfo>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlplatform_p.h>
@@ -51,6 +52,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 +671,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 +841,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 +985,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 +1092,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 +1180,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 +1193,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 +1258,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 +1269,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 +1286,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>();
@@ -1353,12 +1355,12 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
QString stackFrame;
if (frame.column >= 0)
- stackFrame = QString::fromLatin1("%1 (%2:%3:%4)").arg(frame.function,
+ stackFrame = QStringLiteral("%1 (%2:%3:%4)").arg(frame.function,
frame.source,
QString::number(frame.line),
QString::number(frame.column));
else
- stackFrame = QString::fromLatin1("%1 (%2:%3)").arg(frame.function,
+ stackFrame = QStringLiteral("%1 (%2:%3)").arg(frame.function,
frame.source,
QString::number(frame.line));
@@ -1379,7 +1381,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());
@@ -1446,10 +1448,11 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
- if (!QQmlDebugService::isDebuggingEnabled()) {
+ QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (!service) {
logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
} else {
- QQmlProfilerService::instance()->startProfiling(v4->qmlEngine());
+ service->startProfiling(v4->qmlEngine());
logger.debug("Profiling started.");
}
@@ -1465,10 +1468,11 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
const QByteArray baFunction = frame.function.toUtf8();
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
- if (!QQmlDebugService::isDebuggingEnabled()) {
+ QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (!service) {
logger.warning("Ignoring console.profileEnd(): the debug service is disabled.");
} else {
- QQmlProfilerService::instance()->stopProfiling(v4->qmlEngine());
+ service->stopProfiling(v4->qmlEngine());
logger.debug("Profiling ended.");
}
@@ -1612,7 +1616,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 +1730,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..08bbbb8548 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -60,9 +60,10 @@
#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>
+#include <private/qqmlcontextwrapper_p.h>
QT_BEGIN_NAMESPACE
@@ -101,26 +102,26 @@ 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:
int length() const { return callData->argc; }
QV4::ReturnedValue operator[](int idx) { return (idx < callData->argc ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
- QQmlContextData *context() { return ctx; }
- QV4::ReturnedValue qmlGlobal() { return callData->thisObject.asReturnedValue(); }
+ QQmlContextData *context() { return e->qmlContextObject()->context.contextData(); }
+ QV4::ReturnedValue qmlGlobal() { return e->qmlContextObject()->asReturnedValue(); }
void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
QV4::ExecutionEngine *v4engine() const { return e; }
private:
@@ -129,16 +130,14 @@ private:
QQmlV4Function(const QQmlV4Function &);
QQmlV4Function &operator=(const QQmlV4Function &);
- QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal,
- const QV4::Value &global, QQmlContextData *c, QV4::ExecutionEngine *e)
- : callData(callData), retVal(retVal), ctx(c), e(e)
+ QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
+ : callData(callData), retVal(retVal), e(e)
{
- callData->thisObject.val = global.asReturnedValue();
+ callData->thisObject = QV4::Encode::undefined();
}
QV4::CallData *callData;
QV4::Value *retVal;
- QQmlContextData *ctx;
QV4::ExecutionEngine *e;
};
@@ -163,8 +162,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 +189,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..a154da8323 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;
};
@@ -70,65 +70,56 @@ public:
\instantiates QQmlBind
\inqmlmodule QtQml
\ingroup qtquick-interceptors
- \brief Enables the arbitrary creation of property bindings
+ \brief Enables the arbitrary creation of property bindings.
- \section1 Binding to an Inaccessible Property
+ In QML, property bindings result in a dependency between the properties of
+ different objects.
- Sometimes it is necessary to bind to a property of an object that wasn't
- directly instantiated by QML - generally a property of a class exported
- to QML by C++. In these cases, regular property binding doesn't work. Binding
- allows you to bind any value to any property.
+ \section1 Binding to an inaccessible property
+
+ Sometimes it is necessary to bind an object's property to
+ that of another object that isn't directly instantiated by QML, such as a
+ property of a class exported to QML by C++. You can use the Binding type
+ to establish this dependency; binding any value to any object's property.
+
+ For example, in a C++ application that maps an "app.enteredText" property
+ into QML, you can use Binding to update the enteredText property.
- For example, imagine a C++ application that maps an "app.enteredText"
- property into QML. You could use Binding to update the enteredText property
- like this.
\code
TextEdit { id: myTextField; text: "Please type here..." }
Binding { target: app; property: "enteredText"; value: myTextField.text }
\endcode
- Whenever the text in the TextEdit is updated, the C++ property will be
- updated also.
- \section1 "Single-branch" conditional binding
+ When \c{text} changes, the C++ property \c{enteredText} will update
+ automatically.
- In some circumstances you may want to control the value of a property
- only when a certain condition is true (and relinquish control in all
- other circumstances). This often isn't possible to accomplish with a direct
- binding, as you need to supply values for all possible branches.
+ \section1 Conditional bindings
- \code
+ In some cases you may want to modify the value of a property when a certain
+ condition is met but leave it unmodified otherwise. Often, it's not possible
+ to do this with direct bindings, as you have to supply values for all
+ possible branches.
+
+ For example, the code snippet below results in a warning whenever you
+ release the mouse. This is because the value of the binding is undefined
+ when the mouse isn't pressed.
+
+ \qml
// produces warning: "Unable to assign [undefined] to double value"
value: if (mouse.pressed) mouse.mouseX
- \endcode
+ \endqml
- The above example will produce a warning whenever we release the mouse, as the value
- of the binding is undefined when the mouse isn't pressed. We can use the Binding
- type to rewrite the above code and avoid the warning.
+ The Binding type can prevent this warning.
- \code
+ \qml
Binding on value {
when: mouse.pressed
value: mouse.mouseX
}
- \endcode
-
- The Binding type will also restore any previously set direct bindings on
- the property. In that sense, it functions much like a simplified State.
-
- \qml
- // this is equivalent to the above Binding
- State {
- name: "pressed"
- when: mouse.pressed
- PropertyChanges {
- target: obj
- value: mouse.mouseX
- }
- }
\endqml
- If the binding target or binding property is changed, the bound value is
- immediately pushed onto the new target.
+ The Binding type restores any previously set direct bindings on the
+ property.
\sa {Qt QML}
*/
@@ -277,22 +268,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..bc70e68904 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"));
@@ -1062,7 +1057,7 @@ int QQmlDelegateModel::indexOf(QObject *item, QObject *) const
return -1;
}
-void QQmlDelegateModel::setWatchedRoles(QList<QByteArray> roles)
+void QQmlDelegateModel::setWatchedRoles(const QList<QByteArray> &roles)
{
Q_D(QQmlDelegateModel);
d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
@@ -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]);
@@ -3190,7 +3185,7 @@ QString QQmlPartsModel::stringValue(int index, const QString &role)
return QQmlDelegateModelPrivate::get(m_model)->stringValue(m_compositorGroup, index, role);
}
-void QQmlPartsModel::setWatchedRoles(QList<QByteArray> roles)
+void QQmlPartsModel::setWatchedRoles(const QList<QByteArray> &roles)
{
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
@@ -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/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
index 5ebffd5b9d..e222fadec2 100644
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ b/src/qml/types/qqmldelegatemodel_p.h
@@ -96,7 +96,7 @@ public:
ReleaseFlags release(QObject *object);
void cancel(int index);
virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray> roles);
+ virtual void setWatchedRoles(const QList<QByteArray> &roles);
int indexOf(QObject *object, QObject *objectContext) const;
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index dc289eb35e..5c28021c0e 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -356,7 +356,7 @@ public:
ReleaseFlags release(QObject *item);
QString stringValue(int index, const QString &role);
QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
- void setWatchedRoles(QList<QByteArray> roles);
+ void setWatchedRoles(const QList<QByteArray> &roles);
int indexOf(QObject *item, QObject *objectContext) const;
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index ed97690adb..799f7a0b8a 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -88,7 +88,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::Da
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -101,7 +101,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::Data
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -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);
@@ -240,11 +242,12 @@ const ListLayout::Role *ListLayout::getExistingRole(QV4::String *key)
return r;
}
-ModelObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
+QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
{
ListElement *e = elements[elementIndex];
if (e->m_objectCache == 0) {
- e->m_objectCache = new ModelObject(model, elementIndex);
+ e->m_objectCache = new QObject;
+ (void)new ModelNodeMetaObject(e->m_objectCache, model, elementIndex);
}
return e->m_objectCache;
}
@@ -315,8 +318,8 @@ void ListModel::sync(ListModel *src, ListModel *target, QHash<int, ListModel *>
// Update values stored in target meta objects
for (int i=0 ; i < target->elements.count() ; ++i) {
ListElement *e = target->elements[i];
- if (e->m_objectCache)
- e->m_objectCache->updateValues();
+ if (ModelNodeMetaObject *mo = e->objectCache())
+ mo->updateValues();
}
}
@@ -382,9 +385,8 @@ void ListModel::updateCacheIndices()
{
for (int i=0 ; i < elements.count() ; ++i) {
ListElement *e = elements.at(i);
- if (e->m_objectCache) {
- e->m_objectCache->m_elementIndex = i;
- }
+ if (ModelNodeMetaObject *mo = e->objectCache())
+ mo->m_elementIndex = i;
}
}
@@ -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);
@@ -468,9 +470,8 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
roles->append(roleIndex);
}
- if (e->m_objectCache) {
- e->m_objectCache->updateValues(*roles);
- }
+ if (ModelNodeMetaObject *mo = e->objectCache())
+ mo->updateValues(*roles);
}
void ListModel::set(int elementIndex, QV4::Object *object)
@@ -502,7 +503,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 +521,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);
@@ -589,10 +590,12 @@ int ListModel::setOrCreateProperty(int elementIndex, const QString &key, const Q
if (r) {
roleIndex = e->setVariantProperty(*r, data);
- if (roleIndex != -1 && e->m_objectCache) {
+ ModelNodeMetaObject *cache = e->objectCache();
+
+ if (roleIndex != -1 && cache) {
QVector<int> roles;
roles << roleIndex;
- e->m_objectCache->updateValues(roles);
+ cache->updateValues(roles);
}
}
}
@@ -631,6 +634,13 @@ inline char *ListElement::getPropertyMemory(const ListLayout::Role &role)
return mem;
}
+ModelNodeMetaObject *ListElement::objectCache()
+{
+ if (!m_objectCache)
+ return 0;
+ return ModelNodeMetaObject::get(m_objectCache);
+}
+
QString *ListElement::getStringProperty(const ListLayout::Role &role)
{
char *mem = getPropertyMemory(role);
@@ -1169,7 +1179,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());
@@ -1183,11 +1193,11 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
}
roleIndex = setListProperty(role, subModel);
} else {
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
}
} 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);
@@ -1207,15 +1217,48 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
return roleIndex;
}
-ModelObject::ModelObject(QQmlListModel *model, int elementIndex)
-: m_model(model), m_elementIndex(elementIndex), m_meta(new ModelNodeMetaObject(this))
+ModelNodeMetaObject::ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex)
+: QQmlOpenMetaObject(object), m_enabled(false), m_model(model), m_elementIndex(elementIndex), m_initialized(false)
+{}
+
+void ModelNodeMetaObject::initialize()
{
+ const int roleCount = m_model->m_listModel->roleCount();
+ QVector<QByteArray> properties;
+ properties.reserve(roleCount);
+ for (int i = 0 ; i < roleCount ; ++i) {
+ const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
+ QByteArray name = role.name.toUtf8();
+ properties << name;
+ }
+ type()->createProperties(properties);
updateValues();
- setNodeUpdatesEnabled(true);
+ m_enabled = true;
+}
+
+ModelNodeMetaObject::~ModelNodeMetaObject()
+{
+}
+
+QAbstractDynamicMetaObject *ModelNodeMetaObject::toDynamicMetaObject(QObject *object)
+{
+ if (!m_initialized) {
+ m_initialized = true;
+ initialize();
+ }
+ return QQmlOpenMetaObject::toDynamicMetaObject(object);
+}
+
+ModelNodeMetaObject *ModelNodeMetaObject::get(QObject *obj)
+{
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ return static_cast<ModelNodeMetaObject*>(op->metaObject);
}
-void ModelObject::updateValues()
+void ModelNodeMetaObject::updateValues()
{
+ if (!m_initialized)
+ return;
int roleCount = m_model->m_listModel->roleCount();
for (int i=0 ; i < roleCount ; ++i) {
const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
@@ -1225,8 +1268,10 @@ void ModelObject::updateValues()
}
}
-void ModelObject::updateValues(const QVector<int> &roles)
+void ModelNodeMetaObject::updateValues(const QVector<int> &roles)
{
+ if (!m_initialized)
+ return;
int roleCount = roles.count();
for (int i=0 ; i < roleCount ; ++i) {
int roleIndex = roles.at(i);
@@ -1237,15 +1282,6 @@ void ModelObject::updateValues(const QVector<int> &roles)
}
}
-ModelNodeMetaObject::ModelNodeMetaObject(ModelObject *object)
-: QQmlOpenMetaObject(object), m_enabled(false), m_obj(object)
-{
-}
-
-ModelNodeMetaObject::~ModelNodeMetaObject()
-{
-}
-
void ModelNodeMetaObject::propertyWritten(int index)
{
if (!m_enabled)
@@ -1254,17 +1290,75 @@ void ModelNodeMetaObject::propertyWritten(int index)
QString propName = QString::fromUtf8(name(index));
QVariant value = operator[](index);
- QV4::Scope scope(m_obj->m_model->engine());
+ QV4::Scope scope(m_model->engine());
QV4::ScopedValue v(scope, scope.engine->fromVariant(value));
- int roleIndex = m_obj->m_model->m_listModel->setExistingProperty(m_obj->m_elementIndex, propName, v, scope.engine);
+ int roleIndex = m_model->m_listModel->setExistingProperty(m_elementIndex, propName, v, scope.engine);
+ if (roleIndex != -1) {
+ QVector<int> roles;
+ roles << roleIndex;
+ m_model->emitItemsChanged(m_elementIndex, 1, roles);
+ }
+}
+
+namespace QV4 {
+
+void ModelObject::put(Managed *m, String *name, const Value &value)
+{
+ ModelObject *that = static_cast<ModelObject*>(m);
+
+ ExecutionEngine *eng = that->engine();
+ const int elementIndex = that->d()->m_elementIndex;
+ const QString propName = name->toQString();
+ int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName, value, eng);
if (roleIndex != -1) {
QVector<int> roles;
roles << roleIndex;
- m_obj->m_model->emitItemsChanged(m_obj->m_elementIndex, 1, roles);
+ that->d()->m_model->emitItemsChanged(elementIndex, 1, roles);
+ }
+
+ ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
+ if (mo->initialized())
+ mo->emitPropertyNotification(name->toQString().toUtf8());
+}
+
+ReturnedValue ModelObject::get(const Managed *m, String *name, bool *hasProperty)
+{
+ const ModelObject *that = static_cast<const ModelObject*>(m);
+ const ListLayout::Role *role = that->d()->m_model->m_listModel->getExistingRole(name);
+ if (!role)
+ return QObjectWrapper::get(m, name, hasProperty);
+ if (hasProperty)
+ *hasProperty = true;
+ const int elementIndex = that->d()->m_elementIndex;
+ QVariant value = that->d()->m_model->data(elementIndex, role->index);
+ return that->engine()->fromVariant(value);
+}
+
+void ModelObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+{
+ ModelObject *that = static_cast<ModelObject*>(m);
+ ExecutionEngine *v4 = that->engine();
+ name->setM(0);
+ *index = UINT_MAX;
+ if (it->arrayIndex < uint(that->d()->m_model->m_listModel->roleCount())) {
+ Scope scope(that->engine());
+ const ListLayout::Role &role = that->d()->m_model->m_listModel->getExistingRole(it->arrayIndex);
+ ++it->arrayIndex;
+ ScopedString roleName(scope, v4->newString(role.name));
+ name->setM(roleName->d());
+ *attributes = QV4::Attr_Data;
+ QVariant value = that->d()->m_model->data(that->d()->m_elementIndex, role.index);
+ p->value = v4->fromVariant(value);
+ return;
}
+ QV4::QObjectWrapper::advanceIterator(m, it, name, index, p, attributes);
}
+DEFINE_OBJECT_VTABLE(ModelObject);
+
+} // namespace QV4
+
DynamicRoleModelNode::DynamicRoleModelNode(QQmlListModel *owner, int uid) : m_owner(owner), m_uid(uid), m_meta(new DynamicRoleModelNodeMetaObject(this))
{
setNodeUpdatesEnabled(true);
@@ -1330,8 +1424,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 +1492,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));
@@ -2157,8 +2251,8 @@ QQmlV4Handle QQmlListModel::get(int index) const
DynamicRoleModelNode *object = m_modelObjects[index];
result = QV4::QObjectWrapper::wrap(scope.engine, object);
} else {
- ModelObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
- result = QV4::QObjectWrapper::wrap(scope.engine, object);
+ QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
+ result = scope.engine->memoryManager->alloc<QV4::ModelObject>(scope.engine, object, const_cast<QQmlListModel *>(this), index);
}
}
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 75373be47c..b5a5ef3265 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -54,6 +54,10 @@ class QQmlListModelWorkerAgent;
class ListModel;
class ListLayout;
+namespace QV4 {
+struct ModelObject;
+}
+
class Q_QML_PRIVATE_EXPORT QQmlListModel : public QAbstractListModel
{
Q_OBJECT
@@ -94,6 +98,7 @@ private:
friend class QQmlListModelParser;
friend class QQmlListModelWorkerAgent;
friend class ModelObject;
+ friend struct QV4::ModelObject;
friend class ModelNodeMetaObject;
friend class ListModel;
friend class ListElement;
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index 4e3132b860..bd0f028e7a 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -111,56 +111,72 @@ private:
friend class DynamicRoleModelNodeMetaObject;
};
-class ModelObject;
-
class ModelNodeMetaObject : public QQmlOpenMetaObject
{
public:
- ModelNodeMetaObject(ModelObject *object);
+ ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex);
~ModelNodeMetaObject();
+ virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *object);
+
+ static ModelNodeMetaObject *get(QObject *obj);
+
bool m_enabled;
+ QQmlListModel *m_model;
+ int m_elementIndex;
+
+ void updateValues();
+ void updateValues(const QVector<int> &roles);
+
+ bool initialized() const { return m_initialized; }
protected:
void propertyWritten(int index);
private:
-
- ModelObject *m_obj;
-};
-
-class ModelObject : public QObject
-{
- Q_OBJECT
-public:
- ModelObject(QQmlListModel *model, int elementIndex);
-
+ using QQmlOpenMetaObject::setValue;
void setValue(const QByteArray &name, const QVariant &val, bool force)
{
if (force) {
- QVariant existingValue = m_meta->value(name);
+ QVariant existingValue = value(name);
if (existingValue.isValid()) {
- (*m_meta)[name] = QVariant();
+ (*this)[name] = QVariant();
}
}
- m_meta->setValue(name, val);
+ setValue(name, val);
}
- void setNodeUpdatesEnabled(bool enable)
- {
- m_meta->m_enabled = enable;
- }
+ void initialize();
+ bool m_initialized;
+};
- void updateValues();
- void updateValues(const QVector<int> &roles);
+namespace QV4 {
+
+namespace Heap {
+struct ModelObject : public QObjectWrapper {
+ ModelObject(QV4::ExecutionEngine *engine, QObject *object, QQmlListModel *model, int elementIndex)
+ : QObjectWrapper(engine, object)
+ , m_model(model)
+ , m_elementIndex(elementIndex)
+ {}
QQmlListModel *m_model;
int m_elementIndex;
+};
-private:
- ModelNodeMetaObject *m_meta;
+}
+
+struct ModelObject : public QObjectWrapper
+{
+ static void put(Managed *m, String *name, const Value& value);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+
+ V4_OBJECT2(ModelObject, QObjectWrapper)
};
+} // namespace QV4
+
class ListLayout
{
public:
@@ -236,7 +252,7 @@ public:
enum
{
- BLOCK_SIZE = 64 - sizeof(int) - sizeof(ListElement *) - sizeof(ModelObject *)
+ BLOCK_SIZE = 64 - sizeof(int) - sizeof(ListElement *) - sizeof(ModelNodeMetaObject *)
};
private:
@@ -278,11 +294,13 @@ private:
int getUid() const { return uid; }
+ ModelNodeMetaObject *objectCache();
+
char data[BLOCK_SIZE];
ListElement *next;
int uid;
- ModelObject *m_objectCache;
+ QObject *m_objectCache;
friend class ListModel;
};
@@ -315,6 +333,11 @@ public:
return m_layout->getExistingRole(index);
}
+ const ListLayout::Role *getExistingRole(QV4::String *key)
+ {
+ return m_layout->getExistingRole(key);
+ }
+
const ListLayout::Role &getOrCreateListRole(const QString &name)
{
return m_layout->getRoleOrCreate(name, ListLayout::Role::List);
@@ -343,7 +366,7 @@ public:
static void sync(ListModel *src, ListModel *target, QHash<int, ListModel *> *srcModelHash);
- ModelObject *getOrCreateModelObject(QQmlListModel *model, int elementIndex);
+ QObject *getOrCreateModelObject(QQmlListModel *model, int elementIndex);
private:
QPODVector<ListElement *, 4> elements;
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 7081e96070..4b64f24806 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..f6ab2a19e2 100644
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ b/src/qml/types/qqmlobjectmodel_p.h
@@ -61,7 +61,7 @@ public:
virtual ReleaseFlags release(QObject *object) = 0;
virtual void cancel(int) {}
virtual QString stringValue(int, const QString &) = 0;
- virtual void setWatchedRoles(QList<QByteArray> roles) = 0;
+ virtual void setWatchedRoles(const QList<QByteArray> &roles) = 0;
virtual int indexOf(QObject *object, QObject *objectContext) const = 0;
@@ -99,7 +99,7 @@ public:
virtual QObject *object(int index, bool asynchronous=false);
virtual ReleaseFlags release(QObject *object);
virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray>) {}
+ virtual void setWatchedRoles(const QList<QByteArray> &) {}
virtual int indexOf(QObject *object, QObject *objectContext) const;
@@ -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..f83798488c 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);
}
@@ -545,7 +547,7 @@ public:
metaObject = builder.toMetaObject();
*static_cast<QMetaObject *>(this) = *metaObject;
- propertyCache = new QQmlPropertyCache(engine, metaObject);
+ propertyCache = new QQmlPropertyCache(QV8Engine::getV4(engine), metaObject);
}
};
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/qmldevtools/qtqmldevtoolsglobal_p.h b/src/qmldevtools/qtqmldevtoolsglobal_p.h
index fa8731deb6..5cbb5ece72 100644
--- a/src/qmldevtools/qtqmldevtoolsglobal_p.h
+++ b/src/qmldevtools/qtqmldevtoolsglobal_p.h
@@ -49,21 +49,8 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_STATIC
-# if defined(QT_BUILD_QML_LIB)
-# define Q_QML_EXPORT Q_DECL_EXPORT
-# else
-# define Q_QML_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define Q_QML_EXPORT
-#endif
-
-#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
-# define Q_QML_PRIVATE_EXPORT
-#else
-# define Q_QML_PRIVATE_EXPORT Q_QML_EXPORT
-#endif
+#define Q_QML_EXPORT
+#define Q_QML_PRIVATE_EXPORT
QT_END_NAMESPACE
#endif // QTQMLGLOBAL_P_H
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/quicktestevent.cpp b/src/qmltest/quicktestevent.cpp
index df8de14c14..cfa80c4f19 100644
--- a/src/qmltest/quicktestevent.cpp
+++ b/src/qmltest/quicktestevent.cpp
@@ -50,7 +50,7 @@ QuickTestEvent::~QuickTestEvent()
bool QuickTestEvent::keyPress(int key, int modifiers, int delay)
{
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyPress(window, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay);
@@ -59,7 +59,7 @@ bool QuickTestEvent::keyPress(int key, int modifiers, int delay)
bool QuickTestEvent::keyRelease(int key, int modifiers, int delay)
{
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyRelease(window, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay);
@@ -68,7 +68,7 @@ bool QuickTestEvent::keyRelease(int key, int modifiers, int delay)
bool QuickTestEvent::keyClick(int key, int modifiers, int delay)
{
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyClick(window, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay);
@@ -78,7 +78,7 @@ bool QuickTestEvent::keyClick(int key, int modifiers, int delay)
bool QuickTestEvent::keyPressChar(const QString &character, int modifiers, int delay)
{
QTEST_ASSERT(character.length() == 1);
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyPress(window, character[0].toLatin1(), Qt::KeyboardModifiers(modifiers), delay);
@@ -88,7 +88,7 @@ bool QuickTestEvent::keyPressChar(const QString &character, int modifiers, int d
bool QuickTestEvent::keyReleaseChar(const QString &character, int modifiers, int delay)
{
QTEST_ASSERT(character.length() == 1);
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyRelease(window, character[0].toLatin1(), Qt::KeyboardModifiers(modifiers), delay);
@@ -98,7 +98,7 @@ bool QuickTestEvent::keyReleaseChar(const QString &character, int modifiers, int
bool QuickTestEvent::keyClickChar(const QString &character, int modifiers, int delay)
{
QTEST_ASSERT(character.length() == 1);
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyClick(window, character[0].toLatin1(), Qt::KeyboardModifiers(modifiers), delay);
@@ -211,7 +211,7 @@ bool QuickTestEvent::mousePress
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MousePress, view, item,
@@ -226,7 +226,7 @@ bool QuickTestEvent::mouseWheel(
QObject *item, qreal x, qreal y, int buttons,
int modifiers, int xDelta, int yDelta, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseWheel(view, item, Qt::MouseButtons(buttons),
@@ -240,7 +240,7 @@ bool QuickTestEvent::mouseRelease
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseRelease, view, item,
@@ -254,7 +254,7 @@ bool QuickTestEvent::mouseClick
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseClick, view, item,
@@ -268,7 +268,7 @@ bool QuickTestEvent::mouseDoubleClick
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseDoubleClick, view, item,
@@ -282,7 +282,7 @@ bool QuickTestEvent::mouseDoubleClickSequence
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseDoubleClickSequence, view, item,
@@ -295,7 +295,7 @@ bool QuickTestEvent::mouseDoubleClickSequence
bool QuickTestEvent::mouseMove
(QObject *item, qreal x, qreal y, int delay, int buttons)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseMove, view, item,
@@ -304,12 +304,23 @@ bool QuickTestEvent::mouseMove
return true;
}
-QWindow *QuickTestEvent::eventWindow()
+QWindow *QuickTestEvent::eventWindow(QObject *item)
{
- QQuickItem *sgitem = qobject_cast<QQuickItem *>(parent());
- if (sgitem)
- return sgitem->window();
+ QQuickItem *quickItem = qobject_cast<QQuickItem *>(item);
+ if (quickItem)
+ return quickItem->window();
+
+ QQuickItem *testParentitem = qobject_cast<QQuickItem *>(parent());
+ if (testParentitem)
+ return testParentitem->window();
return 0;
}
+QWindow *QuickTestEvent::activeWindow()
+{
+ if (QWindow *window = QGuiApplication::focusWindow())
+ return window;
+ return eventWindow();
+}
+
QT_END_NAMESPACE
diff --git a/src/qmltest/quicktestevent_p.h b/src/qmltest/quicktestevent_p.h
index b7f8f3eda2..338464c6b3 100644
--- a/src/qmltest/quicktestevent_p.h
+++ b/src/qmltest/quicktestevent_p.h
@@ -73,7 +73,8 @@ public Q_SLOTS:
#endif
private:
- QWindow *eventWindow();
+ QWindow *eventWindow(QObject *item = 0);
+ QWindow *activeWindow();
};
QT_END_NAMESPACE
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/designer.pri b/src/quick/designer/designer.pri
index 9f3f7e8be6..eb2141134d 100644
--- a/src/quick/designer/designer.pri
+++ b/src/quick/designer/designer.pri
@@ -1,4 +1,21 @@
-HEADERS += designer/designersupport.h \
- designer/designerwindowmanager_p.h
-SOURCES += designer/designersupport.cpp \
- designer/designerwindowmanager.cpp
+HEADERS += \
+ designer/qquickdesignercustomobjectdata_p.h \
+ designer/qquickdesignersupportitems_p.h \
+ designer/qquickdesignerwindowmanager_p.h \
+ designer/qquickdesignersupportstates_p.h \
+ designer/qquickdesignersupportpropertychanges_p.h \
+ designer/qquickdesignersupportproperties_p.h \
+ designer/qquickdesignersupportmetainfo_p.h \
+ designer/qqmldesignermetaobject_p.h \
+ designer/qquickdesignersupport_p.h
+
+SOURCES += \
+ designer/qquickdesignercustomobjectdata.cpp \
+ designer/qquickdesignersupport.cpp \
+ designer/qquickdesignersupportitems.cpp \
+ designer/qquickdesignersupportmetainfo.cpp \
+ designer/qquickdesignersupportproperties.cpp \
+ designer/qquickdesignersupportpropertychanges.cpp \
+ designer/qquickdesignersupportstates.cpp \
+ designer/qquickdesignerwindowmanager.cpp \
+ designer/qqmldesignermetaobject.cpp
diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp
new file mode 100644
index 0000000000..76c94b242d
--- /dev/null
+++ b/src/quick/designer/qqmldesignermetaobject.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** 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 "qqmldesignermetaobject_p.h"
+
+#include <QSharedPointer>
+#include <QMetaProperty>
+#include <qnumeric.h>
+#include <QDebug>
+
+#include <private/qqmlengine_p.h>
+#include <private/qqmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QHash<QDynamicMetaObjectData *, bool> nodeInstanceMetaObjectList;
+static void (*notifyPropertyChangeCallBack)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName) = 0;
+
+struct MetaPropertyData {
+ inline QPair<QVariant, bool> &getDataRef(int idx) {
+ while (m_data.count() <= idx)
+ m_data << QPair<QVariant, bool>(QVariant(), false);
+ return m_data[idx];
+ }
+
+ inline QVariant &getData(int idx) {
+ QPair<QVariant, bool> &prop = getDataRef(idx);
+ if (!prop.second) {
+ prop.first = QVariant();
+ prop.second = true;
+ }
+ return prop.first;
+ }
+
+ inline bool hasData(int idx) const {
+ if (idx >= m_data.count())
+ return false;
+ return m_data[idx].second;
+ }
+
+ inline int count() { return m_data.count(); }
+
+ QVector<QPair<QVariant, bool> > m_data;
+};
+
+static bool constructedMetaData(const QQmlVMEMetaData* data)
+{
+ return data->propertyCount == 0
+ && data->aliasCount == 0
+ && data->signalCount == 0
+ && data->methodCount == 0;
+}
+
+static QQmlVMEMetaData* fakeMetaData()
+{
+ QQmlVMEMetaData* data = new QQmlVMEMetaData;
+ data->propertyCount = 0;
+ data->aliasCount = 0;
+ data->signalCount = 0;
+ data->methodCount = 0;
+
+ return data;
+}
+
+static const QQmlVMEMetaData* vMEMetaDataForObject(QObject *object)
+{
+ QQmlVMEMetaObject *metaObject = QQmlVMEMetaObject::get(object);
+ if (metaObject)
+ return metaObject->metaData;
+
+ return fakeMetaData();
+}
+
+static QQmlPropertyCache *cacheForObject(QObject *object, QQmlEngine *engine)
+{
+ QQmlVMEMetaObject *metaObject = QQmlVMEMetaObject::get(object);
+ if (metaObject)
+ return metaObject->cache;
+
+ return QQmlEnginePrivate::get(engine)->cache(object);
+}
+
+QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
+{
+ //Avoid setting up multiple MetaObjects on the same QObject
+ QObjectPrivate *op = QObjectPrivate::get(object);
+ QDynamicMetaObjectData *parent = op->metaObject;
+ if (nodeInstanceMetaObjectList.contains(parent))
+ return static_cast<QQmlDesignerMetaObject *>(parent);
+
+ // we just create one and the ownership goes automatically to the object in nodeinstance see init method
+ return new QQmlDesignerMetaObject(object, engine);
+}
+
+void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine)
+{
+ //Creating QQmlOpenMetaObjectType
+ m_type = new QQmlOpenMetaObjectType(metaObjectParent(), engine);
+ m_type->addref();
+ //Assigning type to this
+ copyTypeMetaObject();
+
+ //Assign this to object
+ QObjectPrivate *op = QObjectPrivate::get(object);
+ op->metaObject = this;
+
+ //create cache
+ cache = m_cache = QQmlEnginePrivate::get(engine)->cache(this);
+ cache->addref();
+
+ //If our parent is not a VMEMetaObject we just se the flag to false again
+ if (constructedMetaData(metaData))
+ QQmlData::get(object)->hasVMEMetaObject = false;
+
+ nodeInstanceMetaObjectList.insert(this, true);
+ hasAssignedMetaObjectData = true;
+}
+
+QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine)
+ : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object)),
+ m_context(engine->contextForObject(object)),
+ m_data(new MetaPropertyData),
+ m_cache(0)
+{
+ init(object, engine);
+
+ QQmlData *ddata = QQmlData::get(object, false);
+
+ //Assign cache to object
+ if (ddata && ddata->propertyCache) {
+ cache->setParent(ddata->propertyCache);
+ cache->invalidate(engine, this);
+ ddata->propertyCache = m_cache;
+ }
+
+}
+
+QQmlDesignerMetaObject::~QQmlDesignerMetaObject()
+{
+ if (cache->count() > 1) // qml is crashing because the property cache is not removed from the engine
+ cache->release();
+ else
+ m_type->release();
+
+ nodeInstanceMetaObjectList.remove(this);
+}
+
+void QQmlDesignerMetaObject::createNewDynamicProperty(const QString &name)
+{
+ int id = m_type->createProperty(name.toUtf8());
+ copyTypeMetaObject();
+ setValue(id, QVariant());
+ Q_ASSERT(id >= 0);
+ Q_UNUSED(id);
+
+ //Updating cache
+ QQmlPropertyCache *oldParent = m_cache->parent();
+ QQmlEnginePrivate::get(m_context->engine())->cache(this)->invalidate(m_context->engine(), this);
+ m_cache->setParent(oldParent);
+
+ QQmlProperty property(myObject(), name, m_context);
+ Q_ASSERT(property.isValid());
+}
+
+void QQmlDesignerMetaObject::setValue(int id, const QVariant &value)
+{
+ QPair<QVariant, bool> &prop = m_data->getDataRef(id);
+ prop.first = propertyWriteValue(id, value);
+ prop.second = true;
+ QMetaObject::activate(myObject(), id + m_type->signalOffset(), 0);
+}
+
+QVariant QQmlDesignerMetaObject::propertyWriteValue(int, const QVariant &value)
+{
+ return value;
+}
+
+const QAbstractDynamicMetaObject *QQmlDesignerMetaObject::dynamicMetaObjectParent() const
+{
+ if (QQmlVMEMetaObject::parent.isT1())
+ return QQmlVMEMetaObject::parent.asT1()->toDynamicMetaObject(QQmlVMEMetaObject::object);
+ else
+ return 0;
+}
+
+const QMetaObject *QQmlDesignerMetaObject::metaObjectParent() const
+{
+ if (QQmlVMEMetaObject::parent.isT1())
+ return QQmlVMEMetaObject::parent.asT1()->toDynamicMetaObject(QQmlVMEMetaObject::object);
+
+ return QQmlVMEMetaObject::parent.asT2();
+}
+
+int QQmlDesignerMetaObject::propertyOffset() const
+{
+ return cache->propertyOffset();
+}
+
+int QQmlDesignerMetaObject::openMetaCall(QObject *o, QMetaObject::Call call, int id, void **a)
+{
+ if ((call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty)
+ && id >= m_type->propertyOffset()) {
+ int propId = id - m_type->propertyOffset();
+ if (call == QMetaObject::ReadProperty) {
+ //propertyRead(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = m_data->getData(propId);
+ } else if (call == QMetaObject::WriteProperty) {
+ if (propId <= m_data->count() || m_data->m_data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ //propertyWrite(propId);
+ QPair<QVariant, bool> &prop = m_data->getDataRef(propId);
+ prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
+ prop.second = true;
+ //propertyWritten(propId);
+ activate(myObject(), m_type->signalOffset() + propId, 0);
+ }
+ }
+ return -1;
+ } else {
+ QAbstractDynamicMetaObject *directParent = parent();
+ if (directParent)
+ return directParent->metaCall(o, call, id, a);
+ else
+ return myObject()->qt_metacall(call, id, a);
+ }
+}
+
+int QQmlDesignerMetaObject::metaCall(QObject *o, QMetaObject::Call call, int id, void **a)
+{
+ Q_ASSERT(myObject() == o);
+
+ int metaCallReturnValue = -1;
+
+ const QMetaProperty propertyById = QQmlVMEMetaObject::property(id);
+
+ if (call == QMetaObject::WriteProperty
+ && propertyById.userType() == QMetaType::QVariant
+ && reinterpret_cast<QVariant *>(a[0])->type() == QVariant::Double
+ && qIsNaN(reinterpret_cast<QVariant *>(a[0])->toDouble())) {
+ return -1;
+ }
+
+ if (call == QMetaObject::WriteProperty
+ && propertyById.userType() == QMetaType::Double
+ && qIsNaN(*reinterpret_cast<double*>(a[0]))) {
+ return -1;
+ }
+
+ if (call == QMetaObject::WriteProperty
+ && propertyById.userType() == QMetaType::Float
+ && qIsNaN(*reinterpret_cast<float*>(a[0]))) {
+ return -1;
+ }
+
+ QVariant oldValue;
+
+ if (call == QMetaObject::WriteProperty && !propertyById.hasNotifySignal())
+ {
+ oldValue = propertyById.read(myObject());
+ }
+
+ QAbstractDynamicMetaObject *directParent = parent();
+ if (directParent && id < directParent->propertyOffset()) {
+ metaCallReturnValue = directParent->metaCall(o, call, id, a);
+ } else {
+ openMetaCall(o, call, id, a);
+ }
+
+
+ if (call == QMetaObject::WriteProperty
+ && !propertyById.hasNotifySignal()
+ && oldValue != propertyById.read(myObject()))
+ notifyPropertyChange(id);
+
+ return metaCallReturnValue;
+}
+
+void QQmlDesignerMetaObject::notifyPropertyChange(int id)
+{
+ const QMetaProperty propertyById = property(id);
+
+ if (id < propertyOffset()) {
+ if (notifyPropertyChangeCallBack)
+ notifyPropertyChangeCallBack(myObject(), propertyById.name());
+ } else {
+ if (notifyPropertyChangeCallBack)
+ notifyPropertyChangeCallBack(myObject(), name(id - propertyOffset()));
+ }
+}
+
+int QQmlDesignerMetaObject::count() const
+{
+ return m_type->propertyCount();
+}
+
+QByteArray QQmlDesignerMetaObject::name(int idx) const
+{
+ return m_type->propertyName(idx);
+}
+
+void QQmlDesignerMetaObject::copyTypeMetaObject()
+{
+ *static_cast<QMetaObject *>(this) = *m_type->metaObject();
+}
+
+void QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &))
+{
+ notifyPropertyChangeCallBack = callback;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/designer/qqmldesignermetaobject_p.h b/src/quick/designer/qqmldesignermetaobject_p.h
new file mode 100644
index 0000000000..47f4baad2b
--- /dev/null
+++ b/src/quick/designer/qqmldesignermetaobject_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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 NODEINSTANCEMETAOBJECT_H
+#define NODEINSTANCEMETAOBJECT_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 "qquickdesignersupport_p.h"
+
+#include <QQmlContext>
+#include <QScopedPointer>
+#include <private/qqmlopenmetaobject_p.h>
+#include <private/qqmlvmemetaobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct MetaPropertyData;
+
+class QQmlDesignerMetaObject : public QQmlVMEMetaObject
+{
+public:
+ ~QQmlDesignerMetaObject();
+
+ static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName));
+
+protected:
+ QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine);
+ static QQmlDesignerMetaObject* getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine);
+
+ void createNewDynamicProperty(const QString &name);
+ int openMetaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
+ int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
+ void notifyPropertyChange(int id);
+ void setValue(int id, const QVariant &value);
+ QVariant propertyWriteValue(int, const QVariant &);
+
+ QObject *myObject() const { return QQmlVMEMetaObject::object; }
+ QAbstractDynamicMetaObject *parent() const { return const_cast<QAbstractDynamicMetaObject *>(dynamicMetaObjectParent()); }
+
+ const QAbstractDynamicMetaObject *dynamicMetaObjectParent() const;
+
+ const QMetaObject *metaObjectParent() const;
+
+ int propertyOffset() const;
+
+ int count() const;
+ QByteArray name(int) const;
+
+ void copyTypeMetaObject();
+
+private:
+ void init(QObject *, QQmlEngine *engine);
+
+ QPointer<QQmlContext> m_context;
+ QQmlOpenMetaObjectType *m_type;
+ QScopedPointer<MetaPropertyData> m_data;
+ //QAbstractDynamicMetaObject *m_parent;
+ QQmlPropertyCache *m_cache;
+
+ friend class QQuickDesignerSupportProperties;
+};
+
+QT_END_NAMESPACE
+
+#endif // NODEINSTANCEMETAOBJECT_H
diff --git a/src/quick/designer/qquickdesignercustomobjectdata.cpp b/src/quick/designer/qquickdesignercustomobjectdata.cpp
new file mode 100644
index 0000000000..1666ffb0a5
--- /dev/null
+++ b/src/quick/designer/qquickdesignercustomobjectdata.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** 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 "qquickdesignersupportmetainfo_p.h"
+#include "qquickdesignersupportproperties_p.h"
+
+#include "qquickdesignercustomobjectdata_p.h"
+
+#include <QGlobalStatic>
+#include <QQmlContext>
+#include <QQmlEngine>
+
+#include <private/qqmlbinding_p.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef QHash<QObject*, QQuickDesignerCustomObjectData*> CustomObjectDataHash;
+Q_GLOBAL_STATIC(CustomObjectDataHash, s_designerObjectToDataHash)
+
+struct HandleDestroyedFunctor {
+ QQuickDesignerCustomObjectData *data;
+ void operator()() { data->handleDestroyed(); }
+};
+
+QQuickDesignerCustomObjectData::QQuickDesignerCustomObjectData(QObject *object)
+ : m_object(object)
+{
+ if (object) {
+ populateResetHashes();
+ s_designerObjectToDataHash()->insert(object, this);
+
+ HandleDestroyedFunctor functor;
+ functor.data = this;
+ QObject::connect(object, &QObject::destroyed, functor);
+ }
+}
+
+void QQuickDesignerCustomObjectData::registerData(QObject *object)
+{
+ new QQuickDesignerCustomObjectData(object);
+}
+
+QQuickDesignerCustomObjectData *QQuickDesignerCustomObjectData::get(QObject *object)
+{
+ return s_designerObjectToDataHash()->value(object);
+}
+
+QVariant QQuickDesignerCustomObjectData::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ return data->getResetValue(propertyName);
+
+ return QVariant();
+}
+
+void QQuickDesignerCustomObjectData::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ data->doResetProperty(context, propertyName);
+}
+
+bool QQuickDesignerCustomObjectData::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ return data->hasValidResetBinding(propertyName);
+
+ return false;
+}
+
+bool QQuickDesignerCustomObjectData::hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ return data->hasBindingForProperty(context, propertyName, hasChanged);
+
+ return false;
+}
+
+void QQuickDesignerCustomObjectData::setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ data->setPropertyBinding(context, propertyName, expression);
+}
+
+void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ data->keepBindingFromGettingDeleted(context, propertyName);
+}
+
+void QQuickDesignerCustomObjectData::populateResetHashes()
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList =
+ QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object());
+
+ Q_FOREACH (const QQuickDesignerSupport::PropertyName &propertyName, propertyNameList) {
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), QQmlEngine::contextForObject(object()));
+
+ QQmlAbstractBinding::Ptr binding = QQmlAbstractBinding::Ptr(QQmlPropertyPrivate::binding(property));
+
+ if (binding) {
+ m_resetBindingHash.insert(propertyName, binding);
+ } else if (property.isWritable()) {
+ m_resetValueHash.insert(propertyName, property.read());
+ }
+ }
+}
+
+QObject *QQuickDesignerCustomObjectData::object() const
+{
+ return m_object;
+}
+
+QVariant QQuickDesignerCustomObjectData::getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetValueHash.value(propertyName);
+}
+
+void QQuickDesignerCustomObjectData::doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ if (!property.isValid())
+ return;
+
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(property);
+ if (binding && !(hasValidResetBinding(propertyName) && getResetBinding(propertyName) == binding)) {
+ binding->setEnabled(false, 0);
+ }
+
+
+ if (hasValidResetBinding(propertyName)) {
+ QQmlAbstractBinding *binding = getResetBinding(propertyName);
+
+ QQmlBinding *qmlBinding = dynamic_cast<QQmlBinding*>(binding);
+ if (qmlBinding)
+ qmlBinding->setTarget(property);
+ QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding);
+ if (qmlBinding)
+ qmlBinding->update();
+
+ } else if (property.isResettable()) {
+ property.reset();
+ } else if (property.propertyTypeCategory() == QQmlProperty::List) {
+ QQmlListReference list = qvariant_cast<QQmlListReference>(property.read());
+
+ if (!QQuickDesignerSupportProperties::hasFullImplementedListInterface(list)) {
+ qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!";
+ return;
+ }
+
+ list.clear();
+ } else if (property.isWritable()) {
+ if (property.read() == getResetValue(propertyName))
+ return;
+
+ property.write(getResetValue(propertyName));
+ }
+}
+
+bool QQuickDesignerCustomObjectData::hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetBindingHash.contains(propertyName) && m_resetBindingHash.value(propertyName).data();
+}
+
+QQmlAbstractBinding *QQuickDesignerCustomObjectData::getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetBindingHash.value(propertyName).data();
+}
+
+bool QQuickDesignerCustomObjectData::hasBindingForProperty(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged) const
+{
+ if (QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
+ return false;
+
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ bool hasBinding = QQmlPropertyPrivate::binding(property);
+
+ if (hasChanged) {
+ *hasChanged = hasBinding != m_hasBindingHash.value(propertyName, false);
+ if (*hasChanged)
+ m_hasBindingHash.insert(propertyName, hasBinding);
+ }
+
+ return QQmlPropertyPrivate::binding(property);
+}
+
+void QQuickDesignerCustomObjectData::setPropertyBinding(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ if (!property.isValid())
+ return;
+
+ if (property.isProperty()) {
+ QQmlBinding *binding = new QQmlBinding(expression, object(), context);
+ binding->setTarget(property);
+ binding->setNotifyOnValueChanged(true);
+
+ QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding);
+ //Refcounting is taking take care of deletion
+ binding->update();
+ if (binding->hasError()) {
+ if (property.property().userType() == QVariant::String)
+ property.write(QVariant(QLatin1Char('#') + expression + QLatin1Char('#')));
+ }
+
+ } else {
+ qWarning() << Q_FUNC_INFO << ": Cannot set binding for property" << propertyName << ": property is unknown for type";
+ }
+}
+
+void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ //Refcounting is taking care
+ Q_UNUSED(context)
+ Q_UNUSED(propertyName)
+}
+
+void QQuickDesignerCustomObjectData::handleDestroyed()
+{
+ s_designerObjectToDataHash()->remove(m_object);
+ delete this;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/designer/qquickdesignercustomobjectdata_p.h b/src/quick/designer/qquickdesignercustomobjectdata_p.h
new file mode 100644
index 0000000000..6734540a54
--- /dev/null
+++ b/src/quick/designer/qquickdesignercustomobjectdata_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** 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 DESIGNERCUSTOMOBJECTDATA_H
+#define DESIGNERCUSTOMOBJECTDATA_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 "qquickdesignersupport_p.h"
+
+#include <QHash>
+#include <QObject>
+#include <QVariant>
+
+#include <private/qqmlbinding_p.h>
+
+QT_BEGIN_NAMESPACE
+class QQmlContext;
+
+class QQuickDesignerCustomObjectData
+{
+public:
+ static void registerData(QObject *object);
+ static QQuickDesignerCustomObjectData *get(QObject *object);
+ static QVariant getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static void doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged);
+ static void setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression);
+ static void keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName);
+ void handleDestroyed();
+
+private:
+ QQuickDesignerCustomObjectData(QObject *object);
+ void populateResetHashes();
+ QObject *object() const;
+ QVariant getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ void doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ bool hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ QQmlAbstractBinding *getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ bool hasBindingForProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, bool *hasChanged) const;
+ void setPropertyBinding(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, const QString &expression);
+ void keepBindingFromGettingDeleted(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+
+ QObject *m_object;
+ QHash<QQuickDesignerSupport::PropertyName, QVariant> m_resetValueHash;
+ QHash<QQuickDesignerSupport::PropertyName, QQmlAbstractBinding::Ptr> m_resetBindingHash;
+ mutable QHash<QQuickDesignerSupport::PropertyName, bool> m_hasBindingHash;
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERCUSTOMOBJECTDATA_H
diff --git a/src/quick/designer/designersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp
index 56d2badb62..bc6352a677 100644
--- a/src/quick/designer/designersupport.cpp
+++ b/src/quick/designer/qquickdesignersupport.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "designersupport.h"
+#include "qquickdesignersupport_p.h"
#include <private/qquickitem_p.h>
#include <QtQuick/private/qquickshadereffectsource_p.h>
@@ -46,16 +46,16 @@
#include <private/qqmlcomponentattached_p.h>
#include <private/qqmldata_p.h>
-#include "designerwindowmanager_p.h"
+#include "qquickdesignerwindowmanager_p.h"
QT_BEGIN_NAMESPACE
-DesignerSupport::DesignerSupport()
+QQuickDesignerSupport::QQuickDesignerSupport()
{
}
-DesignerSupport::~DesignerSupport()
+QQuickDesignerSupport::~QQuickDesignerSupport()
{
typedef QHash<QQuickItem*, QSGLayer*>::iterator ItemTextureHashIt;
@@ -67,7 +67,7 @@ DesignerSupport::~DesignerSupport()
}
}
-void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
+void QQuickDesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
{
if (referencedItem == 0)
return;
@@ -100,7 +100,7 @@ void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
}
}
-void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
+void QQuickDesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
{
if (referencedItem == 0)
return;
@@ -109,7 +109,7 @@ void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhid
QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
}
-QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
+QImage QQuickDesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
{
if (referencedItem == 0 || referencedItem->parentItem() == 0) {
qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
@@ -136,7 +136,7 @@ QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRe
return renderImage;
}
-bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
+bool QQuickDesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
{
if (referencedItem == 0)
return false;
@@ -144,7 +144,7 @@ bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
}
-void DesignerSupport::addDirty(QQuickItem *referencedItem, DesignerSupport::DirtyType dirtyType)
+void QQuickDesignerSupport::addDirty(QQuickItem *referencedItem, QQuickDesignerSupport::DirtyType dirtyType)
{
if (referencedItem == 0)
return;
@@ -152,7 +152,7 @@ void DesignerSupport::addDirty(QQuickItem *referencedItem, DesignerSupport::Dirt
QQuickItemPrivate::get(referencedItem)->dirtyAttributes |= dirtyType;
}
-void DesignerSupport::resetDirty(QQuickItem *referencedItem)
+void QQuickDesignerSupport::resetDirty(QQuickItem *referencedItem)
{
if (referencedItem == 0)
return;
@@ -161,7 +161,7 @@ void DesignerSupport::resetDirty(QQuickItem *referencedItem)
QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
}
-QTransform DesignerSupport::windowTransform(QQuickItem *referencedItem)
+QTransform QQuickDesignerSupport::windowTransform(QQuickItem *referencedItem)
{
if (referencedItem == 0)
return QTransform();
@@ -169,7 +169,7 @@ QTransform DesignerSupport::windowTransform(QQuickItem *referencedItem)
return QQuickItemPrivate::get(referencedItem)->itemToWindowTransform();
}
-QTransform DesignerSupport::parentTransform(QQuickItem *referencedItem)
+QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem)
{
if (referencedItem == 0)
return QTransform();
@@ -211,12 +211,9 @@ bool isValidAnchorName(const QString &name)
return anchorNameList.contains(name);
}
-bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
+bool QQuickDesignerSupport::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
@@ -229,9 +226,9 @@ bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
|| anchors->baseline().item == toItem;
}
-bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
+bool QQuickDesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
{
- foreach (QQuickItem *childItem, fromItem->childItems()) {
+ Q_FOREACH (QQuickItem *childItem, fromItem->childItems()) {
if (childItem) {
if (isAnchoredTo(childItem, toItem))
return true;
@@ -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();
}
@@ -278,7 +275,7 @@ QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
return QQuickAnchors::LeftAnchor;
}
-bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
+bool QQuickDesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
{
if (!isValidAnchorName(name))
return false;
@@ -313,19 +310,19 @@ bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
}
-QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
+QQuickItem *QQuickDesignerSupport::anchorFillTargetItem(QQuickItem *item)
{
return anchors(item)->fill();
}
-QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
+QQuickItem *QQuickDesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
{
return anchors(item)->centerIn();
}
-QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
+QPair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
{
QObject *targetObject = 0;
QString targetName;
@@ -350,7 +347,7 @@ QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, con
return QPair<QString, QObject*>(targetName, targetObject);
}
-void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
+void QQuickDesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
{
if (name == QLatin1String("anchors.fill")) {
anchors(item)->resetFill();
@@ -373,7 +370,7 @@ void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
}
}
-void DesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem *item)
+void QQuickDesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem *item)
{
QQmlData *data = QQmlData::get(item);
if (data && data->context) {
@@ -384,24 +381,24 @@ void DesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem
}
}
-QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
+QList<QObject*> QQuickDesignerSupport::statesForItem(QQuickItem *item)
{
QList<QObject*> objectList;
QList<QQuickState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
objectList.reserve(stateList.size());
- foreach (QQuickState* state, stateList)
+ Q_FOREACH (QQuickState* state, stateList)
objectList.append(state);
return objectList;
}
-bool DesignerSupport::isComponentComplete(QQuickItem *item)
+bool QQuickDesignerSupport::isComponentComplete(QQuickItem *item)
{
- return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
+ return QQuickItemPrivate::get(item)->componentComplete;
}
-int DesignerSupport::borderWidth(QQuickItem *item)
+int QQuickDesignerSupport::borderWidth(QQuickItem *item)
{
QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
if (rectangle)
@@ -410,60 +407,71 @@ int DesignerSupport::borderWidth(QQuickItem *item)
return 0;
}
-void DesignerSupport::refreshExpressions(QQmlContext *context)
+void QQuickDesignerSupport::refreshExpressions(QQmlContext *context)
{
QQmlContextPrivate::get(context)->data->refreshExpressions();
}
-void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
+void QQuickDesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
{
QQuickViewPrivate::get(view)->setRootObject(item);
}
-bool DesignerSupport::isValidWidth(QQuickItem *item)
+bool QQuickDesignerSupport::isValidWidth(QQuickItem *item)
{
return QQuickItemPrivate::get(item)->heightValid;
}
-bool DesignerSupport::isValidHeight(QQuickItem *item)
+bool QQuickDesignerSupport::isValidHeight(QQuickItem *item)
{
return QQuickItemPrivate::get(item)->widthValid;
}
-void DesignerSupport::updateDirtyNode(QQuickItem *item)
+void QQuickDesignerSupport::updateDirtyNode(QQuickItem *item)
{
if (item->window())
QQuickWindowPrivate::get(item->window())->updateDirtyNode(item);
}
-void DesignerSupport::activateDesignerWindowManager()
+void QQuickDesignerSupport::activateDesignerWindowManager()
{
- QSGRenderLoop::setInstance(new DesignerWindowManager);
+ QSGRenderLoop::setInstance(new QQuickDesignerWindowManager);
}
-void DesignerSupport::activateDesignerMode()
+void QQuickDesignerSupport::activateDesignerMode()
{
QQmlEnginePrivate::activateDesignerMode();
}
-void DesignerSupport::disableComponentComplete()
+void QQuickDesignerSupport::disableComponentComplete()
{
QQmlVME::disableComponentComplete();
}
-void DesignerSupport::enableComponentComplete()
+void QQuickDesignerSupport::enableComponentComplete()
{
QQmlVME::enableComponentComplete();
}
-void DesignerSupport::createOpenGLContext(QQuickWindow *window)
+void QQuickDesignerSupport::createOpenGLContext(QQuickWindow *window)
{
- DesignerWindowManager::createOpenGLContext(window);
+ QQuickDesignerWindowManager::createOpenGLContext(window);
}
-void DesignerSupport::polishItems(QQuickWindow *window)
+void QQuickDesignerSupport::polishItems(QQuickWindow *window)
{
QQuickWindowPrivate::get(window)->polishItems();
}
+ComponentCompleteDisabler::ComponentCompleteDisabler()
+{
+ QQuickDesignerSupport::disableComponentComplete();
+}
+
+ComponentCompleteDisabler::~ComponentCompleteDisabler()
+{
+ QQuickDesignerSupport::enableComponentComplete();
+}
+
+
QT_END_NAMESPACE
diff --git a/src/quick/designer/designersupport.h b/src/quick/designer/qquickdesignersupport_p.h
index 51fcef4512..e15c109f7b 100644
--- a/src/quick/designer/designersupport.h
+++ b/src/quick/designer/qquickdesignersupport_p.h
@@ -45,7 +45,6 @@
// We mean it.
//
-
#include <QtQuick/qtquickglobal.h>
#include <QtCore/QtGlobal>
#include <QtCore/QHash>
@@ -62,9 +61,13 @@ class QQuickView;
class QObject;
class QQuickWindow;
-class Q_QUICK_EXPORT DesignerSupport
+class Q_QUICK_EXPORT QQuickDesignerSupport
{
public:
+ typedef QByteArray PropertyName;
+ typedef QList<PropertyName> PropertyNameList;
+ typedef QByteArray TypeName;
+
enum DirtyType {
TransformOrigin = 0x00000001,
Transform = 0x00000002,
@@ -95,8 +98,8 @@ public:
};
- DesignerSupport();
- ~DesignerSupport();
+ QQuickDesignerSupport();
+ ~QQuickDesignerSupport();
void refFromEffectItem(QQuickItem *referencedItem, bool hide = true);
void derefFromEffectItem(QQuickItem *referencedItem, bool unhide = true);
@@ -119,7 +122,6 @@ public:
static void resetAnchor(QQuickItem *item, const QString &name);
static void emitComponentCompleteSignalForAttachedProperty(QQuickItem *item);
-
static QList<QObject*> statesForItem(QQuickItem *item);
static bool isComponentComplete(QQuickItem *item);
@@ -149,6 +151,16 @@ private:
QHash<QQuickItem*, QSGLayer*> m_itemTextureHash;
};
+class Q_QUICK_EXPORT ComponentCompleteDisabler
+{
+public:
+ ComponentCompleteDisabler();
+
+ ~ComponentCompleteDisabler();
+};
+
+typedef QQuickDesignerSupport DesignerSupport;
+
QT_END_NAMESPACE
#endif // DESIGNERSUPPORT_H
diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp
new file mode 100644
index 0000000000..4f23fe6630
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportitems.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** 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 "qquickdesignersupportitems_p.h"
+#include "qquickdesignersupportproperties_p.h"
+
+#include <private/qabstractanimation_p.h>
+#include <private/qobject_p.h>
+#include <private/qquickbehavior_p.h>
+#include <private/qquicktext_p.h>
+#include <private/qquicktextinput_p.h>
+#include <private/qquicktextedit_p.h>
+#include <private/qquicktransition_p.h>
+
+#include <private/qquickanimation_p.h>
+#include <private/qqmlmetatype_p.h>
+#include <private/qqmltimer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static void (*fixResourcePathsForObjectCallBack)(QObject*) = 0;
+
+static void stopAnimation(QObject *object)
+{
+ if (object == 0)
+ return;
+
+ QQuickTransition *transition = qobject_cast<QQuickTransition*>(object);
+ QQuickAbstractAnimation *animation = qobject_cast<QQuickAbstractAnimation*>(object);
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(object);
+ if (transition) {
+ transition->setFromState(QString());
+ transition->setToState(QString());
+ } else if (animation) {
+// QQuickScriptAction *scriptAimation = qobject_cast<QQuickScriptAction*>(animation);
+// if (scriptAimation) FIXME
+// scriptAimation->setScript(QQmlScriptString());
+ animation->setLoops(1);
+ animation->complete();
+ animation->setDisableUserControl();
+ } else if (timer) {
+ timer->blockSignals(true);
+ }
+}
+
+static void allSubObjects(QObject *object, QObjectList &objectList)
+{
+ // don't add null pointer and stop if the object is already in the list
+ if (!object || objectList.contains(object))
+ return;
+
+ objectList.append(object);
+
+ for (int index = QObject::staticMetaObject.propertyOffset();
+ index < object->metaObject()->propertyCount();
+ index++) {
+ QMetaProperty metaProperty = object->metaObject()->property(index);
+
+ // search recursive in property objects
+ if (metaProperty.isReadable()
+ && metaProperty.isWritable()
+ && QQmlMetaType::isQObject(metaProperty.userType())) {
+ if (qstrcmp(metaProperty.name(), "parent")) {
+ QObject *propertyObject = QQmlMetaType::toQObject(metaProperty.read(object));
+ allSubObjects(propertyObject, objectList);
+ }
+
+ }
+
+ // search recursive in property object lists
+ if (metaProperty.isReadable()
+ && QQmlMetaType::isList(metaProperty.userType())) {
+ QQmlListReference list(object, metaProperty.name());
+ if (list.canCount() && list.canAt()) {
+ for (int i = 0; i < list.count(); i++) {
+ QObject *propertyObject = list.at(i);
+ allSubObjects(propertyObject, objectList);
+
+ }
+ }
+ }
+ }
+
+ // search recursive in object children list
+ Q_FOREACH (QObject *childObject, object->children()) {
+ allSubObjects(childObject, objectList);
+ }
+
+ // search recursive in quick item childItems list
+ QQuickItem *quickItem = qobject_cast<QQuickItem*>(object);
+ if (quickItem) {
+ Q_FOREACH (QQuickItem *childItem, quickItem->childItems()) {
+ allSubObjects(childItem, objectList);
+ }
+ }
+}
+
+void QQuickDesignerSupportItems::tweakObjects(QObject *object)
+{
+ QObjectList objectList;
+ allSubObjects(object, objectList);
+ Q_FOREACH (QObject* childObject, objectList) {
+ stopAnimation(childObject);
+ if (fixResourcePathsForObjectCallBack)
+ fixResourcePathsForObjectCallBack(childObject);
+ }
+}
+
+static QObject *createDummyWindow(QQmlEngine *engine)
+{
+ QQmlComponent component(engine, QUrl(QStringLiteral("qrc:/qtquickplugin/mockfiles/Window.qml")));
+ return component.create();
+}
+
+static bool isWindowMetaObject(const QMetaObject *metaObject)
+{
+ if (metaObject) {
+ if (metaObject->className() == QByteArrayLiteral("QWindow"))
+ return true;
+
+ return isWindowMetaObject(metaObject->superClass());
+ }
+
+ return false;
+}
+
+static bool isWindow(QObject *object) {
+ if (object)
+ return isWindowMetaObject(object->metaObject());
+
+ return false;
+}
+
+static QQmlType *getQmlType(const QString &typeName, int majorNumber, int minorNumber)
+{
+ return QQmlMetaType::qmlType(typeName, majorNumber, minorNumber);
+}
+
+static bool isCrashingType(QQmlType *type)
+{
+ if (type) {
+ if (type->qmlTypeName() == QStringLiteral("QtMultimedia/MediaPlayer"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtMultimedia/Audio"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/MenuItem"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/Menu"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtQuick/Timer"))
+ return true;
+ }
+
+ return false;
+}
+
+QObject *QQuickDesignerSupportItems::createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
+{
+ ComponentCompleteDisabler disableComponentComplete;
+
+ Q_UNUSED(disableComponentComplete)
+
+ QObject *object = 0;
+ QQmlType *type = getQmlType(typeName, majorNumber, minorNumber);
+
+ if (isCrashingType(type)) {
+ object = new QObject;
+ } else if (type) {
+ if ( type->isComposite()) {
+ object = createComponent(type->sourceUrl(), context);
+ } else
+ {
+ if (type->typeName() == "QQmlComponent") {
+ object = new QQmlComponent(context->engine(), 0);
+ } else {
+ object = type->create();
+ }
+ }
+
+ if (isWindow(object)) {
+ delete object;
+ object = createDummyWindow(context->engine());
+ }
+
+ }
+
+ if (!object) {
+ qWarning() << "QuickDesigner: Cannot create an object of type"
+ << QString::fromLatin1("%1 %2,%3").arg(typeName).arg(majorNumber).arg(minorNumber)
+ << "- type isn't known to declarative meta type system";
+ }
+
+ tweakObjects(object);
+
+ if (object && QQmlEngine::contextForObject(object) == 0)
+ QQmlEngine::setContextForObject(object, context);
+
+ QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
+
+ return object;
+}
+
+QObject *QQuickDesignerSupportItems::createComponent(const QUrl &componentUrl, QQmlContext *context)
+{
+ ComponentCompleteDisabler disableComponentComplete;
+ Q_UNUSED(disableComponentComplete)
+
+ QQmlComponent component(context->engine(), componentUrl);
+
+ QObject *object = component.beginCreate(context);
+ tweakObjects(object);
+ component.completeCreate();
+ QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
+
+ if (component.isError()) {
+ qWarning() << "Error in:" << Q_FUNC_INFO << componentUrl;
+ Q_FOREACH (const QQmlError &error, component.errors())
+ qWarning() << error;
+ }
+ return object;
+}
+
+bool QQuickDesignerSupportItems::objectWasDeleted(QObject *object)
+{
+ return QObjectPrivate::get(object)->wasDeleted;
+}
+
+void QQuickDesignerSupportItems::disableNativeTextRendering(QQuickItem *item)
+{
+ QQuickText *text = qobject_cast<QQuickText*>(item);
+ if (text)
+ text->setRenderType(QQuickText::QtRendering);
+
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(item);
+ if (textInput)
+ textInput->setRenderType(QQuickTextInput::QtRendering);
+
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(item);
+ if (textEdit)
+ textEdit->setRenderType(QQuickTextEdit::QtRendering);
+}
+
+void QQuickDesignerSupportItems::disableTextCursor(QQuickItem *item)
+{
+ Q_FOREACH (QQuickItem *childItem, item->childItems())
+ disableTextCursor(childItem);
+
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(item);
+ if (textInput)
+ textInput->setCursorVisible(false);
+
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(item);
+ if (textEdit)
+ textEdit->setCursorVisible(false);
+}
+
+void QQuickDesignerSupportItems::disableTransition(QObject *object)
+{
+ QQuickTransition *transition = qobject_cast<QQuickTransition*>(object);
+ Q_ASSERT(transition);
+ const QString invalidState = QLatin1String("invalidState");
+ transition->setToState(invalidState);
+ transition->setFromState(invalidState);
+}
+
+void QQuickDesignerSupportItems::disableBehaivour(QObject *object)
+{
+ QQuickBehavior* behavior = qobject_cast<QQuickBehavior*>(object);
+ Q_ASSERT(behavior);
+ behavior->setEnabled(false);
+}
+
+void QQuickDesignerSupportItems::stopUnifiedTimer()
+{
+ QUnifiedTimer::instance()->setSlowdownFactor(0.00001);
+ QUnifiedTimer::instance()->setSlowModeEnabled(true);
+}
+
+void QQuickDesignerSupportItems::registerFixResourcePathsForObjectCallBack(void (*callback)(QObject *))
+{
+ fixResourcePathsForObjectCallBack = callback;
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p.h b/src/quick/designer/qquickdesignersupportitems_p.h
index cf69c3a1f6..c15d651b33 100644
--- a/src/qml/debugger/qqmlconfigurabledebugservice_p.h
+++ b/src/quick/designer/qquickdesignersupportitems_p.h
@@ -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 QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,9 +31,8 @@
**
****************************************************************************/
-
-#ifndef QQMLCONFIGURABLEDEBUGSEVICE_H
-#define QQMLCONFIGURABLEDEBUGSEVICE_H
+#ifndef DESIGNERSUPPORTITEM_H
+#define DESIGNERSUPPORTITEM_H
//
// W A R N I N G
@@ -46,34 +45,33 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
+#include "qquickdesignersupport_p.h"
+
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QList>
+#include <QByteArray>
+#include <QQmlContext>
+#include <QQmlListReference>
QT_BEGIN_NAMESPACE
-class QMutex;
-class QQmlConfigurableDebugServicePrivate;
-class QQmlConfigurableDebugService : public QQmlDebugService
+class Q_QUICK_EXPORT QQuickDesignerSupportItems
{
- Q_OBJECT
public:
- QQmlConfigurableDebugService(const QString &name, float version, QObject *parent = 0);
-
-protected:
- QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
-
- QMutex *configMutex();
- void stopWaiting();
- void init();
-
- void stateChanged(State);
- void engineAboutToBeAdded(QQmlEngine *);
-
- virtual ~QQmlConfigurableDebugService() {}
-private:
- Q_DISABLE_COPY(QQmlConfigurableDebugService)
- Q_DECLARE_PRIVATE(QQmlConfigurableDebugService)
+ static QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context);
+ static QObject *createComponent(const QUrl &componentUrl, QQmlContext *context);
+ static void tweakObjects(QObject *object);
+ static bool objectWasDeleted(QObject *object);
+ static void disableNativeTextRendering(QQuickItem *item);
+ static void disableTextCursor(QQuickItem *item);
+ static void disableTransition(QObject *object);
+ static void disableBehaivour(QObject *object);
+ static void stopUnifiedTimer();
+ static void registerFixResourcePathsForObjectCallBack(void (*callback)(QObject *));
};
QT_END_NAMESPACE
-#endif // QQMLCONFIGURABLEDEBUGSEVICE_H
+#endif // DESIGNERSUPPORTITEM_H
diff --git a/src/qml/qml/ftw/qqmlpool.cpp b/src/quick/designer/qquickdesignersupportmetainfo.cpp
index b86dcba107..c6c7ed38b9 100644
--- a/src/qml/qml/ftw/qqmlpool.cpp
+++ b/src/quick/designer/qquickdesignersupportmetainfo.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 QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,59 +31,38 @@
**
****************************************************************************/
-#include "qqmlpool_p.h"
-#include <stdlib.h>
+#include "qquickdesignersupportmetainfo_p.h"
+#include "qqmldesignermetaobject_p.h"
-#ifdef Q_OS_QNX
-#include <malloc.h>
-#endif
-
-// #define POOL_DEBUG
+#include <private/qqmlmetatype_p.h>
QT_BEGIN_NAMESPACE
-void QQmlPool::newpage()
+bool QQuickDesignerSupportMetaInfo::isSubclassOf(QObject *object, const QByteArray &superTypeName)
{
-#ifdef POOL_DEBUG
- qWarning("QQmlPool: Allocating page");
-#endif
-
- Page *page = (Page *)malloc(sizeof(Page));
- page->header.next = _page;
- page->header.free = page->memory;
- _page = page;
-}
+ if (object == 0)
+ return false;
-void QQmlPool::clear()
-{
-#ifdef POOL_DEBUG
- int count = 0;
-#endif
+ const QMetaObject *metaObject = object->metaObject();
- Class *c = _classList;
- while (c) {
- Class *n = c->_next;
- c->_destroy(c);
-#ifdef POOL_DEBUG
- ++count;
-#endif
- c = n;
- }
+ while (metaObject) {
+ QQmlType *qmlType = QQmlMetaType::qmlType(metaObject);
+ if (qmlType && qmlType->qmlTypeName() == QLatin1String(superTypeName)) // ignore version numbers
+ return true;
-#ifdef POOL_DEBUG
- qWarning("QQmlPool: Destroyed %d objects", count);
-#endif
+ if (metaObject->className() == superTypeName)
+ return true;
- Page *p = _page;
- while (p) {
- Page *n = p->header.next;
- free(p);
- p = n;
+ metaObject = metaObject->superClass();
}
- _classList = 0;
- _page = 0;
+ return false;
}
+void QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &))
+{
+ QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(callback);
+}
QT_END_NAMESPACE
+
diff --git a/src/quick/designer/qquickdesignersupportmetainfo_p.h b/src/quick/designer/qquickdesignersupportmetainfo_p.h
new file mode 100644
index 0000000000..52bf8e3ac0
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportmetainfo_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 DESIGNERSUPPORTMETAINFO_H
+#define DESIGNERSUPPORTMETAINFO_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 "qquickdesignersupport_p.h"
+
+#include <QObject>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportMetaInfo
+{
+public:
+ static bool isSubclassOf(QObject *object, const QByteArray &superTypeName);
+ static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &));
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTMETAINFO_H
diff --git a/src/quick/designer/qquickdesignersupportproperties.cpp b/src/quick/designer/qquickdesignersupportproperties.cpp
new file mode 100644
index 0000000000..96f09ada48
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportproperties.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** 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 "qquickdesignersupportproperties_p.h"
+
+#include "qqmldesignermetaobject_p.h"
+#include "qquickdesignercustomobjectdata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static void addToPropertyNameListIfNotBlackListed(QQuickDesignerSupport::PropertyNameList *propertyNameList,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ if (!QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
+ propertyNameList->append(propertyName);
+}
+
+void QQuickDesignerSupportProperties::createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name)
+{
+ QQmlDesignerMetaObject::getNodeInstanceMetaObject(object, engine)->createNewDynamicProperty(name);
+}
+
+void QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
+{
+ // we just create one and the ownership goes automatically to the object in nodeinstance see init method
+ QQmlDesignerMetaObject::getNodeInstanceMetaObject(object, engine);
+}
+
+bool QQuickDesignerSupportProperties::hasFullImplementedListInterface(const QQmlListReference &list)
+{
+ return list.isValid() && list.canCount() && list.canAt() && list.canAppend() && list.canClear();
+}
+
+void QQuickDesignerSupportProperties::registerCustomData(QObject *object)
+{
+ QQuickDesignerCustomObjectData::registerData(object);
+}
+
+QVariant QQuickDesignerSupportProperties::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ return QQuickDesignerCustomObjectData::getResetValue(object, propertyName);
+}
+
+void QQuickDesignerSupportProperties::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData::doResetProperty(object, context, propertyName);
+}
+
+bool QQuickDesignerSupportProperties::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ return QQuickDesignerCustomObjectData::hasValidResetBinding(object, propertyName);
+}
+
+bool QQuickDesignerSupportProperties::hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged)
+{
+ return QQuickDesignerCustomObjectData::hasBindingForProperty(object, context, propertyName, hasChanged);
+}
+
+void QQuickDesignerSupportProperties::setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickDesignerCustomObjectData::setPropertyBinding(object, context, propertyName, expression);
+}
+
+void QQuickDesignerSupportProperties::keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(object, context, propertyName);
+}
+
+bool QQuickDesignerSupportProperties::isPropertyQObject(const QMetaProperty &metaProperty)
+{
+ return QQmlMetaType::isQObject(metaProperty.userType());
+}
+
+
+QObject *QQuickDesignerSupportProperties::readQObjectProperty(const QMetaProperty &metaProperty, QObject *object)
+{
+ return QQmlMetaType::toQObject(metaProperty.read(object));
+}
+
+void QQuickDesignerSupportProperties::getPropertyCache(QObject *object, QQmlEngine *engine)
+{
+ QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+}
+
+QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propertyNameListForWritableProperties(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName,
+ QObjectList *inspectedObjects)
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList;
+
+ QObjectList localObjectList;
+
+ if (inspectedObjects == 0)
+ inspectedObjects = &localObjectList;
+
+
+ if (inspectedObjects->contains(object))
+ return propertyNameList;
+
+ inspectedObjects->append(object);
+
+ const QMetaObject *metaObject = object->metaObject();
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name()));
+ if (declarativeProperty.isValid() && !declarativeProperty.isWritable() && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) {
+ if (declarativeProperty.name() != QLatin1String("parent")) {
+ QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(propertyNameListForWritableProperties(childObject,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ }
+ } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) {
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType());
+ valueType->setValue(metaProperty.read(object));
+ propertyNameList.append(propertyNameListForWritableProperties(valueType,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ }
+
+ if (metaProperty.isReadable() && metaProperty.isWritable()) {
+ addToPropertyNameListIfNotBlackListed(&propertyNameList,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+bool QQuickDesignerSupportProperties::isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ if (propertyName.contains(".") && propertyName.contains("__"))
+ return true;
+
+ if (propertyName.count(".") > 1)
+ return true;
+
+ return false;
+}
+
+QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allPropertyNames(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName,
+ QObjectList *inspectedObjects)
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList;
+
+ QObjectList localObjectList;
+
+ if (inspectedObjects == 0)
+ inspectedObjects = &localObjectList;
+
+
+ if (inspectedObjects->contains(object))
+ return propertyNameList;
+
+ inspectedObjects->append(object);
+
+
+ const QMetaObject *metaObject = object->metaObject();
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name()));
+ if (declarativeProperty.isValid() && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) {
+ if (declarativeProperty.name() != QLatin1String("parent")) {
+ QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(allPropertyNames(childObject,
+ baseName
+ + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ }
+ } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) {
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType());
+ valueType->setValue(metaProperty.read(object));
+ propertyNameList.append(baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ propertyNameList.append(allPropertyNames(valueType,
+ baseName
+ + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ } else {
+ addToPropertyNameListIfNotBlackListed(&propertyNameList,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+
+QT_END_NAMESPACE
+
+
+
+
diff --git a/src/quick/designer/qquickdesignersupportproperties_p.h b/src/quick/designer/qquickdesignersupportproperties_p.h
new file mode 100644
index 0000000000..187bc6e2a6
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportproperties_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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 DESIGNERSUPPORTPROPERTIES_H
+#define DESIGNERSUPPORTPROPERTIES_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 "qquickdesignersupport_p.h"
+
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QList>
+#include <QByteArray>
+#include <QQmlContext>
+#include <QQmlListReference>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportProperties
+{
+public:
+ static void createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name);
+ static void registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine);
+ static void registerCustomData(QObject *object);
+ static QVariant getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static void doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+
+ static bool hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged);
+ static void setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression);
+ static void keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName);
+
+ static bool isPropertyQObject(const QMetaProperty &metaProperty);
+ static QObject *readQObjectProperty(const QMetaProperty &metaProperty, QObject *object);
+
+ static void getPropertyCache(QObject *object, QQmlEngine *engine);
+ static bool isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName);
+ static QQuickDesignerSupport::PropertyNameList propertyNameListForWritableProperties(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(),
+ QObjectList *inspectedObjects = 0);
+ static QQuickDesignerSupport::PropertyNameList allPropertyNames(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(),
+ QObjectList *inspectedObjects = 0);
+ static bool hasFullImplementedListInterface(const QQmlListReference &list);
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTPROPERTIES_H
diff --git a/src/quick/designer/qquickdesignersupportpropertychanges.cpp b/src/quick/designer/qquickdesignersupportpropertychanges.cpp
new file mode 100644
index 0000000000..92fa637b54
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportpropertychanges.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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 "qquickdesignersupportpropertychanges_p.h"
+
+#include <private/qquickpropertychanges_p.h>
+#include <private/qquickstateoperations_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QQuickDesignerSupportPropertyChanges::attachToState(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->attachToState();
+}
+
+QObject *QQuickDesignerSupportPropertyChanges::targetObject(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return 0;
+
+ return propertyChange->object();
+}
+
+void QQuickDesignerSupportPropertyChanges::removeProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->removeProperty(QString::fromUtf8(propertyName));
+}
+
+QVariant QQuickDesignerSupportPropertyChanges::getProperty(QObject *propertyChanges,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return QVariant();
+
+ return propertyChange->property(QString::fromUtf8(propertyName));
+}
+
+void QQuickDesignerSupportPropertyChanges::changeValue(QObject *propertyChanges,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &value)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->changeValue(QString::fromUtf8(propertyName), value);
+}
+
+void QQuickDesignerSupportPropertyChanges::changeExpression(QObject *propertyChanges,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->changeExpression(QString::fromUtf8(propertyName), expression);
+}
+
+QObject *QQuickDesignerSupportPropertyChanges::stateObject(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return 0;
+
+ return propertyChange->state();
+}
+
+bool QQuickDesignerSupportPropertyChanges::isNormalProperty(const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QMetaObject metaObject = QQuickPropertyChanges::staticMetaObject;
+
+ return (metaObject.indexOfProperty(propertyName) > 0); // 'restoreEntryValues', 'explicit'
+}
+
+void QQuickDesignerSupportPropertyChanges::detachFromState(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->detachFromState();
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/quick/designer/qquickdesignersupportpropertychanges_p.h b/src/quick/designer/qquickdesignersupportpropertychanges_p.h
new file mode 100644
index 0000000000..432383d5b4
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportpropertychanges_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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 DESIGNERSUPPORTPROPERTYCHANGES_H
+#define DESIGNERSUPPORTPROPERTYCHANGES_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 "qquickdesignersupport_p.h"
+
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportPropertyChanges
+{
+public:
+ static void detachFromState(QObject *propertyChanges);
+ static void attachToState(QObject *propertyChanges);
+ static QObject *targetObject(QObject *propertyChanges);
+ static void removeProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName);
+ static QVariant getProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName);
+ static void changeValue(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName, const QVariant &value);
+ static void changeExpression(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName, const QString &expression);
+ static QObject *stateObject(QObject *propertyChanges);
+ static bool isNormalProperty(const QQuickDesignerSupport::PropertyName &propertyName);
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTPROPERTYCHANGES_H
diff --git a/src/quick/designer/qquickdesignersupportstates.cpp b/src/quick/designer/qquickdesignersupportstates.cpp
new file mode 100644
index 0000000000..b75ec7115a
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportstates.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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 "qquickdesignersupportstates_p.h"
+
+#include <private/qquickstategroup_p.h>
+#include <private/qquickpropertychanges_p.h>
+
+QT_BEGIN_NAMESPACE
+
+bool QQuickDesignerSupportStates::isStateActive(QObject *object, QQmlContext *context)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(object);
+
+ if (!stateObject)
+ return false;
+
+ QQuickStateGroup *stateGroup = stateObject->stateGroup();
+
+ QQmlProperty property(object, QLatin1String("name"), context);
+
+ return stateObject && stateGroup && stateGroup->state() == property.read();
+}
+
+void QQuickDesignerSupportStates::activateState(QObject *object, QQmlContext *context)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(object);
+
+ if (!stateObject)
+ return;
+
+ QQuickStateGroup *stateGroup = stateObject->stateGroup();
+
+ QQmlProperty property(object, QLatin1String("name"), context);
+
+ stateGroup->setState(property.read().toString());
+}
+
+void QQuickDesignerSupportStates::deactivateState(QObject *object)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(object);
+
+ if (!stateObject)
+ return;
+
+ QQuickStateGroup *stateGroup = stateObject->stateGroup();
+
+ if (stateGroup)
+ stateGroup->setState(QString());
+}
+
+bool QQuickDesignerSupportStates::changeValueInRevertList(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &value)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(state);
+
+ if (!stateObject)
+ return false;
+
+ return stateObject->changeValueInRevertList(target, QString::fromUtf8(propertyName), value);
+}
+
+bool QQuickDesignerSupportStates::updateStateBinding(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(state);
+
+ if (!stateObject)
+ return false;
+
+ return stateObject->changeValueInRevertList(target, QString::fromUtf8(propertyName), expression);
+}
+
+bool QQuickDesignerSupportStates::resetStateProperty(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant & /* resetValue */)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(state);
+
+ if (!stateObject)
+ return false;
+
+ return stateObject->removeEntryFromRevertList(target, QString::fromUtf8(propertyName));
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/designer/qquickdesignersupportstates_p.h b/src/quick/designer/qquickdesignersupportstates_p.h
new file mode 100644
index 0000000000..daa5a2ff01
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportstates_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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 DESIGNERSUPPORTSTATES_H
+#define DESIGNERSUPPORTSTATES_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 "qquickdesignersupport_p.h"
+
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportStates
+{
+public:
+ static bool isStateActive(QObject *object, QQmlContext *context);
+ static void activateState(QObject *object, QQmlContext *context);
+ static void deactivateState(QObject *object);
+ static bool changeValueInRevertList(QObject *state,
+ QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &value);
+
+ static bool updateStateBinding(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression);
+
+ static bool resetStateProperty(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &);
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTSTATES_H
diff --git a/src/quick/designer/designerwindowmanager.cpp b/src/quick/designer/qquickdesignerwindowmanager.cpp
index f37d6a2180..b1ad42ddb4 100644
--- a/src/quick/designer/designerwindowmanager.cpp
+++ b/src/quick/designer/qquickdesignerwindowmanager.cpp
@@ -31,35 +31,34 @@
**
****************************************************************************/
-#include "designerwindowmanager_p.h"
+#include "qquickdesignerwindowmanager_p.h"
#include "private/qquickwindow_p.h"
#include <QtGui/QOpenGLContext>
#include <QtQuick/QQuickWindow>
-
QT_BEGIN_NAMESPACE
-DesignerWindowManager::DesignerWindowManager()
+QQuickDesignerWindowManager::QQuickDesignerWindowManager()
: m_sgContext(QSGContext::createDefaultContext())
{
m_renderContext.reset(new QSGRenderContext(m_sgContext.data()));
}
-void DesignerWindowManager::show(QQuickWindow *window)
+void QQuickDesignerWindowManager::show(QQuickWindow *window)
{
makeOpenGLContext(window);
}
-void DesignerWindowManager::hide(QQuickWindow *)
+void QQuickDesignerWindowManager::hide(QQuickWindow *)
{
}
-void DesignerWindowManager::windowDestroyed(QQuickWindow *)
+void QQuickDesignerWindowManager::windowDestroyed(QQuickWindow *)
{
}
-void DesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
+void QQuickDesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
{
if (!m_openGlContext) {
m_openGlContext.reset(new QOpenGLContext());
@@ -73,31 +72,31 @@ void DesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
}
}
-void DesignerWindowManager::exposureChanged(QQuickWindow *)
+void QQuickDesignerWindowManager::exposureChanged(QQuickWindow *)
{
}
-QImage DesignerWindowManager::grab(QQuickWindow *)
+QImage QQuickDesignerWindowManager::grab(QQuickWindow *)
{
return QImage();
}
-void DesignerWindowManager::maybeUpdate(QQuickWindow *)
+void QQuickDesignerWindowManager::maybeUpdate(QQuickWindow *)
{
}
-QSGContext *DesignerWindowManager::sceneGraphContext() const
+QSGContext *QQuickDesignerWindowManager::sceneGraphContext() const
{
return m_sgContext.data();
}
-void DesignerWindowManager::createOpenGLContext(QQuickWindow *window)
+void QQuickDesignerWindowManager::createOpenGLContext(QQuickWindow *window)
{
window->create();
window->update();
}
-void DesignerWindowManager::update(QQuickWindow *window)
+void QQuickDesignerWindowManager::update(QQuickWindow *window)
{
makeOpenGLContext(window);
}
diff --git a/src/quick/designer/designerwindowmanager_p.h b/src/quick/designer/qquickdesignerwindowmanager_p.h
index e7a7314c20..6d98e25347 100644
--- a/src/quick/designer/designerwindowmanager_p.h
+++ b/src/quick/designer/qquickdesignerwindowmanager_p.h
@@ -60,11 +60,11 @@ class QSGRenderContext;
class QAnimationDriver;
class QOpenGLContext;
-class DesignerWindowManager : public QSGRenderLoop
+class QQuickDesignerWindowManager : public QSGRenderLoop
{
Q_OBJECT
public:
- DesignerWindowManager();
+ QQuickDesignerWindowManager();
void show(QQuickWindow *window);
void hide(QQuickWindow *window);
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 75507c68d2..9932747dd3 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>
@@ -994,7 +994,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..0a09ee42de 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>
@@ -300,7 +300,7 @@ static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesStr
*/
static bool qSetFontFamilyFromTokens(QFont &font, const QStringList &fontFamilyTokens)
{
- foreach (QString fontFamilyToken, fontFamilyTokens) {
+ foreach (const QString &fontFamilyToken, fontFamilyTokens) {
QFontDatabase fontDatabase;
if (fontDatabase.hasFamily(fontFamilyToken)) {
font.setFamily(fontFamilyToken);
@@ -411,7 +411,7 @@ static QFont qt_font_from_string(const QString& fontString, const QFont &current
int usedTokens = NoTokens;
// Optional properties can be in any order, but font-size and font-family must be last.
- foreach (const QString token, tokens) {
+ foreach (const QString &token, tokens) {
if (token.compare(QLatin1String("normal")) == 0) {
if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) {
// Could be font-style, font-variant or font-weight.
@@ -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 19fb66c19c..ea4398bc71 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -619,7 +619,7 @@ is finished.
\qmlsignal QtQuick::Flickable::movementStarted()
This signal is emitted when the view begins moving due to user
- interaction.
+ interaction or a generated flick().
The corresponding handler is \c onMovementStarted.
*/
@@ -628,9 +628,9 @@ is finished.
\qmlsignal QtQuick::Flickable::movementEnded()
This signal is emitted when the view stops moving due to user
- interaction. If a flick was generated, this signal will
+ interaction or a generated flick(). If a flick was active, this signal will
be emitted once the flick stops. If a flick was not
- generated, this signal will be emitted when the
+ active, this signal will be emitted when the
user stops dragging - i.e. a mouse or touch release.
The corresponding handler is \c onMovementEnded.
@@ -1347,7 +1347,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
@@ -1451,6 +1451,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, true, velocity);
+ event->accept();
}
if (!event->isAccepted())
@@ -1670,6 +1671,9 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry,
\qmlmethod QtQuick::Flickable::flick(qreal xVelocity, qreal yVelocity)
Flicks the content with \a xVelocity horizontally and \a yVelocity vertically in pixels/sec.
+
+ Calling this method will update the corresponding moving and flicking properties and signals,
+ just like a real flick.
*/
void QQuickFlickable::flick(qreal xVelocity, qreal yVelocity)
@@ -1679,8 +1683,15 @@ void QQuickFlickable::flick(qreal xVelocity, qreal yVelocity)
d->vData.reset();
d->hData.velocity = xVelocity;
d->vData.velocity = yVelocity;
+
bool flickedX = d->flickX(xVelocity);
bool flickedY = d->flickY(yVelocity);
+
+ if (flickedX)
+ d->hMoved = true;
+ if (flickedY)
+ d->vMoved = true;
+ movementStarting();
d->flickingStarted(flickedX, flickedY);
}
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 6031315b90..74abd8cf9f 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 99c77488f4..3ac9c6eb1c 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;
}
@@ -918,13 +922,13 @@ void QQuickGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
tempPosition -= bias;
}
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (!topItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (!bottomItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
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 be514ae2f5..421360bd35 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..1ad37ef414 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.path(QUrl::PrettyDecoded);
+ 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 5fd1882216..0c9ee4fe73 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);
@@ -1608,6 +1608,85 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror)
}
}
+/*!
+ \qmltype EnterKey
+ \instantiates QQuickEnterKeyAttached
+ \inqmlmodule QtQuick
+ \ingroup qtquick-input
+ \since 5.6
+ \brief Provides a property to manipulate the appearance of Enter key on
+ an on-screen keyboard.
+
+ The EnterKey attached property is used to manipulate the appearance and
+ behavior of the Enter key on an on-screen keyboard.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick::EnterKey::type
+
+ Holds the type of the Enter key.
+
+ \note Not all of these values are supported on all platforms. For
+ unsupported values the default key is used instead.
+
+ \value Qt.EnterKeyDefault The default Enter key. This can be either a
+ button to accept the input and close the
+ keyboard, or a \e Return button to enter a
+ newline in case of a multi-line input field.
+
+ \value Qt.EnterKeyReturn Show a \e Return button that inserts a
+ newline.
+
+ \value Qt.EnterKeyDone Show a \e {"Done"} button. Typically, the
+ keyboard is expected to close when the button
+ is pressed.
+
+ \value Qt.EnterKeyGo Show a \e {"Go"} button. Typically used in an
+ address bar when entering a URL.
+
+ \value Qt.EnterKeySend Show a \e {"Send"} button.
+
+ \value Qt.EnterKeySearch Show a \e {"Search"} button.
+
+ \value Qt.EnterKeyNext Show a \e {"Next"} button. Typically used in a
+ form to allow navigating to the next input
+ field without the keyboard closing.
+
+ \value Qt.EnterKeyPrevious Show a \e {"Previous"} button.
+*/
+
+QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent)
+ : QObject(parent), itemPrivate(0), keyType(Qt::EnterKeyDefault)
+{
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
+ itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->extra.value().enterKeyAttached = this;
+ } else
+ qmlInfo(parent) << tr("EnterKey attached property only works with Items");
+}
+
+QQuickEnterKeyAttached *QQuickEnterKeyAttached::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickEnterKeyAttached(object);
+}
+
+Qt::EnterKeyType QQuickEnterKeyAttached::type() const
+{
+ return keyType;
+}
+
+void QQuickEnterKeyAttached::setType(Qt::EnterKeyType type)
+{
+ if (keyType != type) {
+ keyType = type;
+#ifndef QT_NO_IM
+ if (itemPrivate && itemPrivate->activeFocus)
+ QGuiApplication::inputMethod()->update(Qt::ImEnterKeyType);
+#endif
+ typeChanged();
+ }
+}
+
void QQuickItemPrivate::setAccessible()
{
isAccessible = true;
@@ -2776,7 +2855,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 +2887,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)
@@ -3960,6 +4039,11 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
case Qt::ImPreferredLanguage:
if (d->extra.isAllocated() && d->extra->keyHandler)
v = d->extra->keyHandler->inputMethodQuery(query);
+ break;
+ case Qt::ImEnterKeyType:
+ if (d->extra.isAllocated() && d->extra->enterKeyAttached)
+ v = d->extra->enterKeyAttached->type();
+ break;
default:
break;
}
@@ -4102,7 +4186,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();
}
}
@@ -7404,6 +7488,7 @@ QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
, m_effectComponent(0)
, m_effect(0)
, m_effectSource(0)
+ , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically)
{
}
@@ -7475,6 +7560,7 @@ void QQuickItemLayer::activate()
m_effectSource->setMipmap(m_mipmap);
m_effectSource->setWrapMode(m_wrapMode);
m_effectSource->setFormat(m_format);
+ m_effectSource->setTextureMirroring(m_textureMirroring);
if (m_effectComponent)
activateEffect();
@@ -7728,6 +7814,35 @@ void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
}
/*!
+ \qmlproperty enumeration QtQuick::Item::layer.textureMirroring
+ \since 5.6
+
+ This property defines how the generated OpenGL texture should be mirrored.
+ The default value is \c{ShaderEffectSource.MirrorVertically}.
+ Custom mirroring can be useful if the generated texture is directly accessed by custom shaders,
+ such as those specified by ShaderEffect. If no effect is specified for the layered
+ item, mirroring has no effect on the UI representation of the item.
+
+ \list
+ \li ShaderEffectSource.NoMirroring - No mirroring
+ \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis.
+ \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis.
+ \endlist
+ */
+
+void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring)
+{
+ if (mirroring == m_textureMirroring)
+ return;
+ m_textureMirroring = mirroring;
+
+ if (m_effectSource)
+ m_effectSource->setTextureMirroring(m_textureMirroring);
+
+ emit textureMirroringChanged(mirroring);
+}
+
+/*!
\qmlproperty string QtQuick::Item::layer.samplerName
Holds the name of the effect's source texture property.
@@ -7839,6 +7954,7 @@ void QQuickItemLayer::updateMatrix()
QQuickItemPrivate::ExtraData::ExtraData()
: z(0), scale(1), rotation(0), opacity(1),
contents(0), screenAttached(0), layoutDirectionAttached(0),
+ enterKeyAttached(0),
keyHandler(0), layer(0),
effectRefCount(0), hideRefCount(0),
opacityNode(0), clipNode(0), rootNode(0),
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..942b51bf68 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -78,6 +78,7 @@ QT_BEGIN_NAMESPACE
class QNetworkReply;
class QQuickItemKeyFilter;
class QQuickLayoutMirroringAttached;
+class QQuickEnterKeyAttached;
class QQuickScreenAttached;
class QQuickContents : public QQuickItemChangeListener
@@ -142,6 +143,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
Q_PROPERTY(QQuickShaderEffectSource::Format format READ format WRITE setFormat NOTIFY formatChanged)
Q_PROPERTY(QByteArray samplerName READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QQmlComponent *effect READ effect WRITE setEffect NOTIFY effectChanged)
+ Q_PROPERTY(QQuickShaderEffectSource::TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged)
public:
QQuickItemLayer(QQuickItem *item);
~QQuickItemLayer();
@@ -176,6 +178,9 @@ public:
QQmlComponent *effect() const { return m_effectComponent; }
void setEffect(QQmlComponent *effect);
+ QQuickShaderEffectSource::TextureMirroring textureMirroring() const { return m_textureMirroring; }
+ void setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring);
+
QQuickShaderEffectSource *effectSource() const { return m_effectSource; }
void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE;
@@ -199,6 +204,7 @@ Q_SIGNALS:
void smoothChanged(bool smooth);
void formatChanged(QQuickShaderEffectSource::Format format);
void sourceRectChanged(const QRectF &sourceRect);
+ void textureMirroringChanged(QQuickShaderEffectSource::TextureMirroring mirroring);
private:
friend class QQuickTransformAnimatorJob;
@@ -222,6 +228,7 @@ private:
QQmlComponent *m_effectComponent;
QQuickItem *m_effect;
QQuickShaderEffectSource *m_effectSource;
+ QQuickShaderEffectSource::TextureMirroring m_textureMirroring;
};
class Q_QUICK_PRIVATE_EXPORT QQuickItemPrivate : public QObjectPrivate
@@ -338,6 +345,7 @@ public:
QQuickContents *contents;
QQuickScreenAttached *screenAttached;
QQuickLayoutMirroringAttached* layoutDirectionAttached;
+ QQuickEnterKeyAttached *enterKeyAttached;
QQuickItemKeyFilter *keyHandler;
mutable QQuickItemLayer *layer;
#ifndef QT_NO_CURSOR
@@ -645,8 +653,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 +670,7 @@ public:
void setBacktab(QQuickItem *);
enum Priority { BeforeItem, AfterItem };
+ Q_ENUM(Priority)
Priority priority() const;
void setPriority(Priority);
@@ -710,6 +717,27 @@ private:
QQuickItemPrivate *itemPrivate;
};
+class QQuickEnterKeyAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::EnterKeyType type READ type WRITE setType NOTIFY typeChanged)
+
+public:
+ explicit QQuickEnterKeyAttached(QObject *parent = Q_NULLPTR);
+
+ Qt::EnterKeyType type() const;
+ void setType(Qt::EnterKeyType type);
+
+ static QQuickEnterKeyAttached *qmlAttachedProperties(QObject *);
+Q_SIGNALS:
+ void typeChanged();
+private:
+ friend class QQuickItemPrivate;
+ QQuickItemPrivate *itemPrivate;
+
+ Qt::EnterKeyType keyType;
+};
+
class QQuickKeysAttachedPrivate : public QObjectPrivate
{
public:
@@ -739,8 +767,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 +781,7 @@ public:
}
enum Priority { BeforeItem, AfterItem};
+ Q_ENUM(Priority)
Priority priority() const;
void setPriority(Priority);
@@ -895,5 +922,7 @@ QML_DECLARE_TYPE(QQuickKeyNavigationAttached)
QML_DECLARE_TYPEINFO(QQuickKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickLayoutMirroringAttached)
QML_DECLARE_TYPEINFO(QQuickLayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QQuickEnterKeyAttached)
+QML_DECLARE_TYPEINFO(QQuickEnterKeyAttached, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKITEM_P_H
diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h
index 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..62e0adcb0a 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,19 @@ 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");
+ qmlRegisterUncreatableType<QQuickEnterKeyAttached, 6>(uri, 2, 6, "EnterKey",
+ QQuickEnterKeyAttached::tr("EnterKey is only available via attached properties"));
+ qmlRegisterType<QQuickShaderEffectSource, 1>(uri, 2, 6, "ShaderEffectSource");
}
static void initResources()
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 01ef1e65f7..d4c8c3f8ee 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;
}
}
@@ -905,11 +910,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
qreal pos = isContentFlowReversed() ? -position() - size() : position();
FxViewItem *item = visibleItem(idx);
- qreal maxExtent;
- if (layoutOrientation() == Qt::Vertical)
- maxExtent = isContentFlowReversed() ? q->minYExtent()-size(): -q->maxYExtent();
- else
- maxExtent = isContentFlowReversed() ? q->minXExtent()-size(): -q->maxXExtent();
+ qreal maxExtent = calculatedMaxExtent();
if (!item) {
qreal itemPos = positionAt(idx);
changedVisibleIndex(idx);
@@ -955,11 +956,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
break;
}
pos = qMin(pos, maxExtent);
- qreal minExtent;
- if (layoutOrientation() == Qt::Vertical)
- minExtent = isContentFlowReversed() ? q->maxYExtent()-size(): -q->minYExtent();
- else
- minExtent = isContentFlowReversed() ? q->maxXExtent()-size(): -q->minXExtent();
+ qreal minExtent = calculatedMinExtent();
pos = qMax(pos, minExtent);
moveReason = QQuickItemViewPrivate::Other;
q->cancelFlick();
@@ -1130,6 +1127,29 @@ qreal QQuickItemViewPrivate::maxExtentForAxis(const AxisData &axisData, bool for
return extent;
}
+qreal QQuickItemViewPrivate::calculatedMinExtent() const
+{
+ Q_Q(const QQuickItemView);
+ qreal minExtent;
+ if (layoutOrientation() == Qt::Vertical)
+ minExtent = isContentFlowReversed() ? q->maxYExtent() - size(): -q->minYExtent();
+ else
+ minExtent = isContentFlowReversed() ? q->maxXExtent() - size(): -q->minXExtent();
+ return minExtent;
+
+}
+
+qreal QQuickItemViewPrivate::calculatedMaxExtent() const
+{
+ Q_Q(const QQuickItemView);
+ qreal maxExtent;
+ if (layoutOrientation() == Qt::Vertical)
+ maxExtent = isContentFlowReversed() ? q->minYExtent() - size(): -q->maxYExtent();
+ else
+ maxExtent = isContentFlowReversed() ? q->minXExtent() - size(): -q->maxXExtent();
+ return maxExtent;
+}
+
// for debugging only
void QQuickItemViewPrivate::checkVisible() const
{
@@ -1199,7 +1219,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;
@@ -1277,10 +1297,12 @@ void QQuickItemView::trackedPositionChanged()
if (trackedPos < pos + d->highlightRangeStart)
pos = trackedPos - d->highlightRangeStart;
if (d->highlightRange != StrictlyEnforceRange) {
- if (pos > d->endPosition() - d->size())
- pos = d->endPosition() - d->size();
- if (pos < d->startPosition())
- pos = d->startPosition();
+ qreal maxExtent = d->calculatedMaxExtent();
+ if (pos > maxExtent)
+ pos = maxExtent;
+ qreal minExtent = d->calculatedMinExtent();
+ if (pos < minExtent)
+ pos = minExtent;
}
} else {
if (d->trackedItem != d->currentItem) {
@@ -1344,7 +1366,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 +1663,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 +1687,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 +1830,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 +1848,7 @@ void QQuickItemViewPrivate::layout()
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartOffset());
+ updateViewport();
if (transitioner)
transitioner->setPopulateTransitionEnabled(false);
inLayout = false;
@@ -1967,7 +1992,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 +2032,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 +2067,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 +2120,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 +2380,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 +2451,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 a8352b229e..0931db4e56 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;
@@ -198,6 +200,8 @@ public:
qreal minExtentForAxis(const AxisData &axisData, bool forXAxis) const;
qreal maxExtentForAxis(const AxisData &axisData, bool forXAxis) const;
+ qreal calculatedMinExtent() const;
+ qreal calculatedMaxExtent() const;
void applyPendingChanges();
bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult);
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 20b6dd5b36..a1d765d6ec 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 Q_DECL_OVERRIDE {
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 Q_DECL_OVERRIDE {
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);
}
@@ -599,10 +609,11 @@ bool QQuickListViewPrivate::releaseItem(FxViewItem *item)
if (!item || !model)
return true;
+ QPointer<QQuickItem> it = item->item;
QQuickListViewAttached *att = static_cast<QQuickListViewAttached*>(item->attached);
bool released = QQuickItemViewPrivate::releaseItem(item);
- if (released && att && att->m_sectionItem) {
+ if (released && it && att && att->m_sectionItem) {
// We hold no more references to this item
int i = 0;
do {
@@ -657,10 +668,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 +685,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 +722,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 +741,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 {
@@ -1457,13 +1470,13 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
tempPosition -= bias;
}
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (!topItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (!bottomItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
@@ -2844,7 +2857,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..d46e25d255 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -576,7 +576,6 @@ void QQuickLoader::setSource(QQmlV4Function *args)
if (!ipv->isUndefined()) {
d->disposeInitialPropertyValues();
d->initialPropertyValues.set(args->v4engine(), ipv);
- d->qmlGlobalForIpv.set(args->v4engine(), args->qmlGlobal());
}
setSource(sourceUrl, false); // already cleared and set ipv above.
@@ -642,11 +641,11 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
QQmlComponentPrivate *d = QQmlComponentPrivate::get(component);
Q_ASSERT(d && d->engine);
- QV4::ExecutionEngine *v4 = qmlGlobalForIpv.engine();
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(d->engine);
Q_ASSERT(v4);
QV4::Scope scope(v4);
QV4::ScopedValue ipv(scope, initialPropertyValues.value());
- d->initializeObjectWithInitialProperties(*qmlGlobalForIpv.valueRef(), ipv, obj);
+ d->initializeObjectWithInitialProperties(ipv, obj);
}
void QQuickLoaderIncubator::statusChanged(Status status)
@@ -943,7 +942,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..9677318b58 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
@@ -102,7 +102,6 @@ public:
QQmlContext *itemContext;
QQuickLoaderIncubator *incubator;
QV4::PersistentValue initialPropertyValues;
- QV4::PersistentValue qmlGlobalForIpv;
bool updatingSize: 1;
bool active : 1;
bool loadingFromSource : 1;
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/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index 8a00dbaf92..16afa39bdd 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -125,7 +125,7 @@ private:
};
class QQuickRectanglePrivate;
-class Q_AUTOTEST_EXPORT QQuickRectangle : public QQuickItem
+class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem
{
Q_OBJECT
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 6b0b9c3a06..cc4cec443a 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -46,7 +46,6 @@
#include <QtQuick/QQuickWindow>
#include <QtQuick/private/qquickwindow_p.h>
-#include <private/qqmlprofilerservice_p.h>
#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index 0168d73c8f..09b504b742 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()
@@ -360,8 +361,8 @@ void QQuickRepeater::clear()
if (QQuickItem *item = d->deletables.at(i)) {
if (complete)
emit itemRemoved(i, item);
- item->setParentItem(0);
d->model->release(item);
+ item->setParentItem(0);
}
}
}
@@ -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);
@@ -465,8 +466,8 @@ void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
d->deletables.remove(index);
emit itemRemoved(index, item);
if (item) {
- item->setParentItem(0);
d->model->release(item);
+ item->setParentItem(0);
}
--d->itemCount;
}
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.cpp b/src/quick/items/qquickshadereffectsource.cpp
index bf69fe4277..2effc0d0ae 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -189,6 +189,7 @@ QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent)
, m_mipmap(false)
, m_recursive(false)
, m_grab(true)
+ , m_textureMirroring(MirrorVertically)
{
setFlag(ItemHasContents);
}
@@ -543,6 +544,37 @@ void QQuickShaderEffectSource::setRecursive(bool enabled)
}
/*!
+ \qmlproperty enumeration QtQuick::ShaderEffectSource::textureMirroring
+ \since 5.6
+
+ This property defines how the generated OpenGL texture should be mirrored.
+ The default value is \c{ShaderEffectSource.MirrorVertically}.
+ Custom mirroring can be useful if the generated texture is directly accessed by custom shaders,
+ such as those specified by ShaderEffect. Mirroring has no effect on the UI representation of
+ the ShaderEffectSource item itself.
+
+ \list
+ \li ShaderEffectSource.NoMirroring - No mirroring
+ \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis.
+ \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis.
+ \endlist
+*/
+
+QQuickShaderEffectSource::TextureMirroring QQuickShaderEffectSource::textureMirroring() const
+{
+ return QQuickShaderEffectSource::TextureMirroring(m_textureMirroring);
+}
+
+void QQuickShaderEffectSource::setTextureMirroring(TextureMirroring mirroring)
+{
+ if (mirroring == QQuickShaderEffectSource::TextureMirroring(m_textureMirroring))
+ return;
+ m_textureMirroring = mirroring;
+ update();
+ emit textureMirroringChanged();
+}
+
+/*!
\qmlmethod QtQuick::ShaderEffectSource::scheduleUpdate()
Schedules a re-rendering of the texture for the next frame.
@@ -642,6 +674,8 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
m_texture->setRecursive(m_recursive);
m_texture->setFormat(GLenum(m_format));
m_texture->setHasMipmaps(m_mipmap);
+ m_texture->setMirrorHorizontal(m_textureMirroring & MirrorHorizontally);
+ m_texture->setMirrorVertical(m_textureMirroring & MirrorVertically);
if (m_grab)
m_texture->scheduleUpdate();
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 31e503be42..629acf0f55 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -66,8 +66,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi
Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
+ Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION 1)
- Q_ENUMS(Format WrapMode)
public:
enum WrapMode {
ClampToEdge,
@@ -75,12 +75,21 @@ public:
RepeatVertically,
Repeat
};
+ Q_ENUM(WrapMode)
enum Format {
Alpha = GL_ALPHA,
RGB = GL_RGB,
RGBA = GL_RGBA
};
+ Q_ENUM(Format)
+
+ enum TextureMirroring {
+ NoMirroring = 0x00,
+ MirrorHorizontally = 0x01,
+ MirrorVertically = 0x02
+ };
+ Q_ENUM(TextureMirroring)
QQuickShaderEffectSource(QQuickItem *parent = 0);
~QQuickShaderEffectSource();
@@ -112,6 +121,9 @@ public:
bool recursive() const;
void setRecursive(bool enabled);
+ TextureMirroring textureMirroring() const;
+ void setTextureMirroring(TextureMirroring mirroring);
+
bool isTextureProvider() const Q_DECL_OVERRIDE { return true; }
QSGTextureProvider *textureProvider() const Q_DECL_OVERRIDE;
@@ -127,6 +139,7 @@ Q_SIGNALS:
void hideSourceChanged();
void mipmapChanged();
void recursiveChanged();
+ void textureMirroringChanged();
void scheduledUpdateCompleted();
@@ -156,6 +169,7 @@ private:
uint m_mipmap : 1;
uint m_recursive : 1;
uint m_grab : 1;
+ uint m_textureMirroring : 2; // Stores TextureMirroring enum
};
QT_END_NAMESPACE
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 205571f2e7..924c455872 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)
@@ -284,6 +293,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
@@ -327,9 +404,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) {
@@ -410,7 +487,7 @@ void QQuickTextPrivate::updateBaseline(qreal baseline, qreal dy)
yoff = dy/2;
}
- q->setBaselineOffset(baseline + yoff);
+ q->setBaselineOffset(baseline + yoff + q->topPadding());
}
void QQuickTextPrivate::updateSize()
@@ -430,6 +507,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
@@ -442,8 +522,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;
@@ -464,7 +544,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.
@@ -488,15 +568,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)
@@ -505,7 +585,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;
@@ -513,11 +593,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)
@@ -623,7 +703,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)
@@ -635,10 +715,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);
@@ -691,10 +771,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;
@@ -730,7 +811,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;
@@ -751,8 +832,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;
@@ -922,7 +1003,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.
@@ -939,8 +1020,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.
@@ -993,7 +1077,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))
@@ -1073,7 +1157,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);
@@ -1096,7 +1180,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
default:
break;
}
- elideLayout->setAdditionalFormats(formats);
+ elideLayout->setFormats(formats);
}
elideLayout->setFont(layout.font());
@@ -1361,6 +1445,16 @@ QQuickText::~QQuickText()
*/
/*!
+ \qmlproperty string QtQuick::Text::font.styleName
+ \since 5.6
+
+ Sets the style name of the font.
+
+ The style name is case insensitive. If set, the font will be matched against style name instead
+ of the font properties \l weight, \l bold and \l italic.
+*/
+
+/*!
\qmlproperty bool QtQuick::Text::font.bold
Sets whether the font weight is bold.
@@ -2279,7 +2373,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)
@@ -2296,11 +2390,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;
@@ -2570,7 +2664,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) {
@@ -2587,14 +2681,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();
@@ -2812,4 +2907,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 cd14008728..f43df691b5 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;
@@ -160,6 +169,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 6929bb44a2..7bc5fab677 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 cd1cf5eef1..dc4e301a36 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);
@@ -199,6 +206,17 @@ QString QQuickTextEdit::text() const
*/
/*!
+ \qmlproperty string QtQuick::TextEdit::font.styleName
+ \since 5.6
+
+ Sets the style name of the font.
+
+ The style name is case insensitive. If set, the font will be matched against style name instead
+ of the font properties \l weight, \l bold and \l italic.
+*/
+
+
+/*!
\qmlproperty bool QtQuick::TextEdit::font.bold
Sets whether the font weight is bold.
@@ -699,6 +717,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 +1732,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 +1869,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 +1902,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 +1923,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 +1943,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 +1957,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 {
@@ -1888,13 +1976,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
@@ -1903,15 +1991,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);
@@ -2016,6 +2105,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);
@@ -2099,7 +2201,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)
@@ -2225,7 +2327,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
@@ -2243,13 +2345,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
@@ -2264,12 +2366,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);
@@ -2416,16 +2518,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);
@@ -2436,7 +2541,6 @@ QQuickTextNode *QQuickTextEditPrivate::createTextNode()
Q_Q(QQuickTextEdit);
QQuickTextNode* node = new QQuickTextNode(q);
node->setUseNativeRenderer(renderType == QQuickTextEdit::NativeRendering);
- node->initEngine(color, selectedTextColor, selectionColor);
return node;
}
@@ -2588,6 +2692,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
@@ -2680,7 +2793,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 5c67d914a5..c29acf3c83 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()
{
}
@@ -222,6 +229,16 @@ QString QQuickTextInputPrivate::realText() const
*/
/*!
+ \qmlproperty string QtQuick::TextInput::font.styleName
+ \since 5.6
+
+ Sets the style name of the font.
+
+ The style name is case insensitive. If set, the font will be matched against style name instead
+ of the font properties \l weight, \l bold and \l italic.
+*/
+
+/*!
\qmlproperty bool QtQuick::TextInput::font.bold
Sets whether the font weight is bold.
@@ -786,8 +803,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 +927,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 +1323,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 +1583,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 +1646,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 +1714,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 +1756,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 +2508,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 +2731,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 +2739,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 +2820,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 +2852,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 +2876,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 +3250,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 +3269,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
}
}
}
- m_textLayout.setAdditionalFormats(formats);
+ m_textLayout.setFormats(formats);
updateDisplayText(/*force*/ true);
if ((cursorPositionChanged && !emitCursorPositionChanged())
@@ -4273,6 +4178,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 +4428,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 efe79b382e..2b7f94d8bf 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -882,7 +882,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..0b3cfa17b5 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -38,8 +38,9 @@
#include "qquickitem_p.h"
#include "qquickitemchangelistener_p.h"
+#include <private/qqmldebugconnector_p.h>
#include <private/qquickprofiler_p.h>
-#include <private/qqmlinspectorservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <QtQml/qqmlengine.h>
@@ -86,8 +87,9 @@ void QQuickViewPrivate::init(QQmlEngine* e)
rootItemMarker.set(v4, v);
}
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->addView(q);
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->addView(q);
}
QQuickViewPrivate::QQuickViewPrivate()
@@ -97,8 +99,9 @@ QQuickViewPrivate::QQuickViewPrivate()
QQuickViewPrivate::~QQuickViewPrivate()
{
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->removeView(q_func());
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->removeView(q_func());
}
void QQuickViewPrivate::execute()
@@ -345,6 +348,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 +370,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 +511,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 5958edf29f..8ab910f299 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -64,7 +64,6 @@
#include <QtQuick/private/qquickpixmapcache_p.h>
-#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qopenglvertexarrayobject_p.h>
@@ -83,8 +82,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 +258,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();
}
@@ -370,12 +368,15 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
if (!customRenderStage || !customRenderStage->render()) {
int fboId = 0;
const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
- renderer->setDeviceRect(QRect(QPoint(0, 0), size * devicePixelRatio));
if (renderTargetId) {
+ QRect rect(QPoint(0, 0), renderTargetSize);
fboId = renderTargetId;
- renderer->setViewportRect(QRect(QPoint(0, 0), renderTargetSize));
+ renderer->setDeviceRect(rect);
+ renderer->setViewportRect(rect);
} else {
- renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio));
+ QRect rect(QPoint(0, 0), devicePixelRatio * size);
+ renderer->setDeviceRect(rect);
+ renderer->setViewportRect(rect);
}
renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size));
renderer->setDevicePixelRatio(devicePixelRatio);
@@ -2385,7 +2386,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) {
@@ -2729,7 +2732,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
@@ -2738,13 +2741,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));
@@ -2752,11 +2751,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));
@@ -2764,10 +2766,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)
@@ -2870,7 +2873,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
@@ -2888,14 +2894,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) {
@@ -2919,9 +2920,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);
@@ -2938,10 +2938,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()) {
@@ -3307,12 +3303,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");
@@ -3382,6 +3373,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.
+
*/
/*!
@@ -3586,12 +3582,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.
@@ -3613,14 +3618,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);
}
@@ -4115,6 +4119,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}
*/
@@ -4140,8 +4145,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(),
@@ -4153,16 +4167,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..d5bf9fba81 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..ecf6865895 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -38,7 +38,8 @@
#include <private/qquickitemsmodule_p.h>
#include <private/qquickaccessiblefactory_p.h>
-#include <private/qqmlenginedebugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlcontext_p.h>
@@ -133,7 +134,6 @@ void QQmlQtQuick2DebugStatesDelegate::updateBinding(QQmlContext *context,
QQmlContextData::get(context), fileName,
line, column);
newBinding->setTarget(property);
- newBinding->setNotifyOnValueChanged(true);
}
state->changeBindingInRevertList(object, propertyName, newBinding);
@@ -187,11 +187,13 @@ void QQmlQtQuick2Module::defineModule()
QAccessible::installFactory(&qQuickAccessibleFactory);
#endif
- if (QQmlDebugService::isDebuggingEnabled()) {
- QQmlEngineDebugService::instance()->setStatesDelegate(
- new QQmlQtQuick2DebugStatesDelegate);
- QQuickProfiler::initialize();
- }
+ QQmlEngineDebugService *debugService = QQmlDebugConnector::service<QQmlEngineDebugService>();
+ if (debugService)
+ debugService->setStatesDelegate(new QQmlQtQuick2DebugStatesDelegate);
+
+ QQmlProfilerService *profilerService = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (profilerService)
+ QQuickProfiler::initialize(profilerService);
}
void QQmlQtQuick2Module::undefineModule()
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 42b9f526d0..8632ea0b52 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;
@@ -487,6 +487,11 @@ void Updater::visitGeometryNode(Node *n)
if (e->batch)
renderer->invalidateBatchAndOverlappingRenderOrders(e->batch);
}
+ if (n->dirtyState & QSGNode::DirtyMaterial) {
+ Element *e = n->element();
+ if (e->batch && e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare)
+ renderer->invalidateBatchAndOverlappingRenderOrders(e->batch);
+ }
}
SHADOWNODE_TRAVERSE(n) visitNode(*child);
@@ -1081,6 +1086,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;
}
}
@@ -1213,10 +1221,7 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
if (e->isMaterialBlended != blended) {
m_rebuild |= Renderer::FullRebuild;
e->isMaterialBlended = blended;
- } else if (e->batch) {
- if (e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare)
- invalidateBatchAndOverlappingRenderOrders(e->batch);
- } else {
+ } else if (!e->batch) {
m_rebuild |= Renderer::BuildBatches;
}
}
@@ -2554,8 +2559,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";
@@ -2571,6 +2583,7 @@ void Renderer::render()
}
qDebug() << "Renderer::render()" << this << type;
+ timer.start();
}
if (m_vao)
@@ -2597,6 +2610,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();
@@ -2609,7 +2623,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:";
@@ -2629,8 +2645,11 @@ void Renderer::render()
}
}
}
+ } else {
+ if (Q_UNLIKELY(debug_render())) timePrepareOpaque = timePrepareAlpha = timer.restart();
}
+
deleteRemovedElements();
if (m_rebuild != 0) {
@@ -2646,6 +2665,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;
@@ -2660,6 +2681,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) {
@@ -2670,6 +2693,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);
@@ -2680,6 +2704,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 6b494dbaeb..d19fa0e17d 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/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 1253711a94..fde3fa06b2 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -195,6 +195,8 @@ public:
virtual void setFormat(GLenum format) = 0;
virtual void setHasMipmaps(bool mipmap) = 0;
virtual void setDevicePixelRatio(qreal ratio) = 0;
+ virtual void setMirrorHorizontal(bool mirror) = 0;
+ virtual void setMirrorVertical(bool mirror) = 0;
Q_SLOT virtual void markDirtyTexture() = 0;
Q_SLOT virtual void invalidated() = 0;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 418d571ae6..150f8475d8 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,15 +59,10 @@
#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>
-#include <private/qqmlprofilerservice_p.h>
-
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
/*
@@ -572,35 +566,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 +642,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 +733,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/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
index cca0712ece..fa69f911dd 100644
--- a/src/quick/scenegraph/qsgdefaultlayer.cpp
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -97,6 +97,8 @@ QSGDefaultLayer::QSGDefaultLayer(QSGRenderContext *context)
, m_multisamplingChecked(false)
, m_multisampling(false)
, m_grab(false)
+ , m_mirrorHorizontal(false)
+ , m_mirrorVertical(true)
{
}
@@ -259,6 +261,16 @@ void QSGDefaultLayer::setRecursive(bool recursive)
m_recursive = recursive;
}
+void QSGDefaultLayer::setMirrorHorizontal(bool mirror)
+{
+ m_mirrorHorizontal = mirror;
+}
+
+void QSGDefaultLayer::setMirrorVertical(bool mirror)
+{
+ m_mirrorVertical = mirror;
+}
+
void QSGDefaultLayer::markDirtyTexture()
{
m_dirtyTexture = true;
@@ -365,7 +377,10 @@ void QSGDefaultLayer::grab()
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
- QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
+ QRectF mirrored(m_mirrorHorizontal ? m_rect.right() : m_rect.left(),
+ m_mirrorVertical ? m_rect.bottom() : m_rect.top(),
+ m_mirrorHorizontal ? -m_rect.width() : m_rect.width(),
+ m_mirrorVertical ? -m_rect.height() : m_rect.height());
m_renderer->setProjectionMatrixToRect(mirrored);
m_renderer->setClearColor(Qt::transparent);
@@ -428,3 +443,11 @@ QImage QSGDefaultLayer::toImage() const
return QImage();
}
+
+QRectF QSGDefaultLayer::normalizedTextureSubRect() const
+{
+ return QRectF(m_mirrorHorizontal ? 1 : 0,
+ m_mirrorVertical ? 0 : 1,
+ m_mirrorHorizontal ? -1 : 1,
+ m_mirrorVertical ? 1 : -1);
+}
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
index 0ba7109ef6..7baaed5f67 100644
--- a/src/quick/scenegraph/qsgdefaultlayer_p.h
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -78,10 +78,18 @@ public:
void setDevicePixelRatio(qreal ratio) Q_DECL_OVERRIDE { m_device_pixel_ratio = ratio; }
+ bool mirrorHorizontal() const { return bool(m_mirrorHorizontal); }
+ void setMirrorHorizontal(bool mirror) Q_DECL_OVERRIDE;
+
+ bool mirrorVertical() const { return bool(m_mirrorVertical); }
+ void setMirrorVertical(bool mirror) Q_DECL_OVERRIDE;
+
void scheduleUpdate() Q_DECL_OVERRIDE;
QImage toImage() const Q_DECL_OVERRIDE;
+ QRectF normalizedTextureSubRect() const Q_DECL_OVERRIDE;
+
public Q_SLOTS:
void markDirtyTexture() Q_DECL_OVERRIDE;
void invalidated() Q_DECL_OVERRIDE;
@@ -115,6 +123,8 @@ private:
uint m_multisamplingChecked : 1;
uint m_multisampling : 1;
uint m_grab : 1;
+ uint m_mirrorHorizontal : 1;
+ uint m_mirrorVertical : 1;
};
#endif // QSGDEFAULTLAYER_P_H
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 4d3f34c71c..3059b750f2 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -102,6 +102,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 2cebbaf484..4b78fefa99 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -54,7 +54,8 @@
#include <private/qquickanimatorcontroller_p.h>
#include <private/qquickprofiler_p.h>
-#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmldebugconnector_p.h>
#include <private/qquickshadereffectnode_p.h>
@@ -147,6 +148,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 +204,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 +357,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 +407,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 +429,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
@@ -666,7 +692,7 @@ void QSGRenderThread::run()
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "run()";
animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0);
animatorDriver->install();
- if (QQmlDebugService::isDebuggingEnabled())
+ if (QQmlDebugConnector::service<QQmlProfilerService>())
QQuickProfiler::registerAnimationCallback();
while (active) {
@@ -993,20 +1019,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;
@@ -1242,6 +1268,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 2a8e3c281c..0182f8abfb 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 f8f40b4705..ca70aecb8e 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/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 6aa7bedc5b..391e0b7347 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -285,6 +286,7 @@ public:
QV4::ScopedValue vbold(scope, obj->get((s = v4->newString(QStringLiteral("bold")))));
QV4::ScopedValue vcap(scope, obj->get((s = v4->newString(QStringLiteral("capitalization")))));
QV4::ScopedValue vfam(scope, obj->get((s = v4->newString(QStringLiteral("family")))));
+ QV4::ScopedValue vstyle(scope, obj->get((s = v4->newString(QStringLiteral("styleName")))));
QV4::ScopedValue vital(scope, obj->get((s = v4->newString(QStringLiteral("italic")))));
QV4::ScopedValue vlspac(scope, obj->get((s = v4->newString(QStringLiteral("letterSpacing")))));
QV4::ScopedValue vpixsz(scope, obj->get((s = v4->newString(QStringLiteral("pixelSize")))));
@@ -307,6 +309,10 @@ public:
retn.setFamily(vfam->toQString());
if (ok) *ok = true;
}
+ if (vstyle->isString()) {
+ retn.setStyleName(vstyle->toQString());
+ if (ok) *ok = true;
+ }
if (vital->isBoolean()) {
retn.setItalic(vital->booleanValue());
if (ok) *ok = true;
@@ -392,132 +398,37 @@ public:
return 0;
}
- template<typename T>
- bool typedInit(void *data, size_t dataSize)
- {
- ASSERT_VALID_SIZE(dataSize, sizeof(T));
- T *t = reinterpret_cast<T *>(data);
- new (t) T();
- return true;
- }
-
- bool init(int type, void *data, size_t dataSize)
+ bool init(int type, QVariant& dst) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QColor:
- return typedInit<QColor>(data, dataSize);
- case QMetaType::QFont:
- return typedInit<QFont>(data, dataSize);
- case QMetaType::QVector2D:
- return typedInit<QVector2D>(data, dataSize);
- case QMetaType::QVector3D:
- return typedInit<QVector3D>(data, dataSize);
- case QMetaType::QVector4D:
- return typedInit<QVector4D>(data, dataSize);
- case QMetaType::QQuaternion:
- return typedInit<QQuaternion>(data, dataSize);
- case QMetaType::QMatrix4x4:
- {
- if (dataSize >= sizeof(QMatrix4x4))
- return typedInit<QMatrix4x4>(data, dataSize);
-
- // special case: init matrix-containing qvariant.
- Q_ASSERT(dataSize >= sizeof(QVariant));
- QVariant *matvar = reinterpret_cast<QVariant *>(data);
- new (matvar) QVariant(QMatrix4x4());
+ dst.setValue<QColor>(QColor());
return true;
- }
- default: break;
- }
-
- return false;
- }
-
- template<typename T>
- bool typedDestroy(void *data, size_t dataSize)
- {
- ASSERT_VALID_SIZE(dataSize, sizeof(T));
- T *t = reinterpret_cast<T *>(data);
- t->~T();
- return true;
- }
-
- bool destroy(int type, void *data, size_t dataSize)
- {
- switch (type) {
- case QMetaType::QColor:
- return typedDestroy<QColor>(data, dataSize);
case QMetaType::QFont:
- return typedDestroy<QFont>(data, dataSize);
- case QMetaType::QVector2D:
- return typedDestroy<QVector2D>(data, dataSize);
- case QMetaType::QVector3D:
- return typedDestroy<QVector3D>(data, dataSize);
- case QMetaType::QVector4D:
- return typedDestroy<QVector4D>(data, dataSize);
- case QMetaType::QQuaternion:
- return typedDestroy<QQuaternion>(data, dataSize);
- case QMetaType::QMatrix4x4:
- {
- if (dataSize >= sizeof(QMatrix4x4))
- return typedDestroy<QMatrix4x4>(data, dataSize);
-
- // special case: destroying matrix-containing qvariant.
- Q_ASSERT(dataSize >= sizeof(QVariant));
- QVariant *matvar = reinterpret_cast<QVariant *>(data);
- matvar->~QVariant();
+ dst.setValue<QFont>(QFont());
return true;
- }
- default: break;
- }
-
- return false;
- }
-
- template<typename T>
- bool typedCopyConstruct(const void *src, void *dst, size_t dstSize)
- {
- ASSERT_VALID_SIZE(dstSize, sizeof(T));
- const T *srcT = reinterpret_cast<const T *>(src);
- T *destT = reinterpret_cast<T *>(dst);
- new (destT) T(*srcT);
- return true;
- }
-
- bool copy(int type, const void *src, void *dst, size_t dstSize)
- {
- switch (type) {
- case QMetaType::QColor:
- return typedCopyConstruct<QColor>(src, dst, dstSize);
- case QMetaType::QFont:
- return typedCopyConstruct<QFont>(src, dst, dstSize);
case QMetaType::QVector2D:
- return typedCopyConstruct<QVector2D>(src, dst, dstSize);
+ dst.setValue<QVector2D>(QVector2D());
+ return true;
case QMetaType::QVector3D:
- return typedCopyConstruct<QVector3D>(src, dst, dstSize);
+ dst.setValue<QVector3D>(QVector3D());
+ return true;
case QMetaType::QVector4D:
- return typedCopyConstruct<QVector4D>(src, dst, dstSize);
+ dst.setValue<QVector4D>(QVector4D());
+ return true;
case QMetaType::QQuaternion:
- return typedCopyConstruct<QQuaternion>(src, dst, dstSize);
+ dst.setValue<QQuaternion>(QQuaternion());
+ return true;
case QMetaType::QMatrix4x4:
- {
- if (dstSize >= sizeof(QMatrix4x4))
- return typedCopyConstruct<QMatrix4x4>(src, dst, dstSize);
-
- // special case: copying matrix into variant.
- Q_ASSERT(dstSize >= sizeof(QVariant));
- const QMatrix4x4 *srcMatrix = reinterpret_cast<const QMatrix4x4 *>(src);
- QVariant *dstMatrixVar = reinterpret_cast<QVariant *>(dst);
- new (dstMatrixVar) QVariant(*srcMatrix);
+ dst.setValue<QMatrix4x4>(QMatrix4x4());
return true;
- }
default: break;
}
return false;
}
- bool create(int type, int argc, const void *argv[], QVariant *v)
+ bool create(int type, int argc, const void *argv[], QVariant *v) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QFont: // must specify via js-object.
@@ -580,7 +491,7 @@ public:
return true;
}
- bool createFromString(int type, const QString &s, void *data, size_t dataSize)
+ bool createFromString(int type, const QString &s, void *data, size_t dataSize) Q_DECL_OVERRIDE
{
bool ok = false;
@@ -596,22 +507,14 @@ public:
case QMetaType::QQuaternion:
return createFromStringTyped<QQuaternion>(data, dataSize, quaternionFromString(s, &ok));
case QMetaType::QMatrix4x4:
- {
- if (dataSize >= sizeof(QMatrix4x4))
- return createFromStringTyped<QMatrix4x4>(data, dataSize, matrix4x4FromString(s, &ok));
-
- Q_ASSERT(dataSize >= sizeof(QVariant));
- QVariant *matVar = reinterpret_cast<QVariant *>(data);
- new (matVar) QVariant(matrix4x4FromString(s, &ok));
- return true;
- }
+ return createFromStringTyped<QMatrix4x4>(data, dataSize, matrix4x4FromString(s, &ok));
default: break;
}
return false;
}
- bool createStringFrom(int type, const void *data, QString *s)
+ bool createStringFrom(int type, const void *data, QString *s) Q_DECL_OVERRIDE
{
if (type == QMetaType::QColor) {
const QColor *color = reinterpret_cast<const QColor *>(data);
@@ -622,7 +525,7 @@ public:
return false;
}
- bool variantFromString(const QString &s, QVariant *v)
+ bool variantFromString(const QString &s, QVariant *v) Q_DECL_OVERRIDE
{
QColor c(s);
if (c.isValid()) {
@@ -665,7 +568,7 @@ public:
return false;
}
- bool variantFromString(int type, const QString &s, QVariant *v)
+ bool variantFromString(int type, const QString &s, QVariant *v) Q_DECL_OVERRIDE
{
bool ok = false;
@@ -708,7 +611,7 @@ public:
return false;
}
- bool variantFromJsObject(int type, QQmlV4Handle object, QV4::ExecutionEngine *v4, QVariant *v)
+ bool variantFromJsObject(int type, QQmlV4Handle object, QV4::ExecutionEngine *v4, QVariant *v) Q_DECL_OVERRIDE
{
QV4::Scope scope(v4);
#ifndef QT_NO_DEBUG
@@ -729,12 +632,12 @@ public:
}
template<typename T>
- bool typedEqual(const void *lhs, const void *rhs)
+ bool typedEqual(const void *lhs, const QVariant& rhs)
{
- return (*(reinterpret_cast<const T *>(lhs)) == *(reinterpret_cast<const T *>(rhs)));
+ return (*(reinterpret_cast<const T *>(lhs)) == rhs.value<T>());
}
- bool equal(int type, const void *lhs, const void *rhs, size_t rhsSize)
+ bool equal(int type, const void *lhs, const QVariant &rhs) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QColor:
@@ -750,14 +653,7 @@ public:
case QMetaType::QQuaternion:
return typedEqual<QQuaternion>(lhs, rhs);
case QMetaType::QMatrix4x4:
- {
- if (rhsSize >= sizeof(QMatrix4x4))
- return typedEqual<QMatrix4x4>(lhs, rhs);
-
- Q_ASSERT(rhsSize >= sizeof(QVariant));
- QMatrix4x4 rhsmat = reinterpret_cast<const QVariant *>(rhs)->value<QMatrix4x4>();
- return typedEqual<QMatrix4x4>(lhs, &rhsmat);
- }
+ return typedEqual<QMatrix4x4>(lhs, rhs);
default: break;
}
@@ -774,8 +670,9 @@ public:
return true;
}
- bool store(int type, const void *src, void *dst, size_t dstSize)
+ bool store(int type, const void *src, void *dst, size_t dstSize) Q_DECL_OVERRIDE
{
+ Q_UNUSED(dstSize);
switch (type) {
case QMetaType::QColor:
{
@@ -785,81 +682,41 @@ public:
new (color) QColor(QColor::fromRgba(*rgb));
return true;
}
- case QMetaType::QFont:
- return typedStore<QFont>(src, dst, dstSize);
- case QMetaType::QVector2D:
- return typedStore<QVector2D>(src, dst, dstSize);
- case QMetaType::QVector3D:
- return typedStore<QVector3D>(src, dst, dstSize);
- case QMetaType::QVector4D:
- return typedStore<QVector4D>(src, dst, dstSize);
- case QMetaType::QQuaternion:
- return typedStore<QQuaternion>(src, dst, dstSize);
- case QMetaType::QMatrix4x4:
- {
- if (dstSize >= sizeof(QMatrix4x4))
- return typedStore<QMatrix4x4>(src, dst, dstSize);
-
- // special case: storing matrix into variant
- // eg, QVMEMO QVMEVariant data cell is big enough to store
- // QVariant, but not large enough to store QMatrix4x4.
- Q_ASSERT(dstSize >= sizeof(QVariant));
- const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
- QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
- new (dstMatVar) QVariant(*srcMat);
- return true;
- }
- default: break;
+ default: break;
}
return false;
}
template<typename T>
- bool typedRead(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+ bool typedRead(const QVariant& src, int dstType, void *dst)
{
T *dstT = reinterpret_cast<T *>(dst);
- if (srcType == dstType) {
- ASSERT_VALID_SIZE(srcSize, sizeof(T));
- const T *srcT = reinterpret_cast<const T *>(src);
- *dstT = *srcT;
+ if (src.type() == static_cast<uint>(dstType)) {
+ *dstT = src.value<T>();
} else {
*dstT = T();
}
return true;
}
- bool read(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+ bool read(const QVariant &src, void *dst, int dstType) Q_DECL_OVERRIDE
{
switch (dstType) {
case QMetaType::QColor:
- return typedRead<QColor>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QColor>(src, dstType, dst);
case QMetaType::QFont:
- return typedRead<QFont>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QFont>(src, dstType, dst);
case QMetaType::QVector2D:
- return typedRead<QVector2D>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QVector2D>(src, dstType, dst);
case QMetaType::QVector3D:
- return typedRead<QVector3D>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QVector3D>(src, dstType, dst);
case QMetaType::QVector4D:
- return typedRead<QVector4D>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QVector4D>(src, dstType, dst);
case QMetaType::QQuaternion:
- return typedRead<QQuaternion>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QQuaternion>(src, dstType, dst);
case QMetaType::QMatrix4x4:
- {
- if (srcSize >= sizeof(QMatrix4x4))
- return typedRead<QMatrix4x4>(srcType, src, srcSize, dstType, dst);
-
- // the source data may be stored in a QVariant.
- QMatrix4x4 *dstMat = reinterpret_cast<QMatrix4x4 *>(dst);
- if (srcType == dstType) {
- Q_ASSERT(srcSize >= sizeof(QVariant));
- const QVariant *srcMatVar = reinterpret_cast<const QVariant *>(src);
- *dstMat = srcMatVar->value<QMatrix4x4>();
- } else {
- *dstMat = QMatrix4x4();
- }
- return true;
- }
+ return typedRead<QMatrix4x4>(src, dstType, dst);
default: break;
}
@@ -867,51 +724,33 @@ public:
}
template<typename T>
- bool typedWrite(const void *src, void *dst, size_t dstSize)
+ bool typedWrite(const void *src, QVariant& dst)
{
- ASSERT_VALID_SIZE(dstSize, sizeof(T));
const T *srcT = reinterpret_cast<const T *>(src);
- T *dstT = reinterpret_cast<T *>(dst);
- if (*dstT != *srcT) {
- *dstT = *srcT;
+ if (dst.value<T>() != *srcT) {
+ dst = *srcT;
return true;
}
return false;
}
- bool write(int type, const void *src, void *dst, size_t dstSize)
+ bool write(int type, const void *src, QVariant& dst) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QColor:
- return typedWrite<QColor>(src, dst, dstSize);
+ return typedWrite<QColor>(src, dst);
case QMetaType::QFont:
- return typedWrite<QFont>(src, dst, dstSize);
+ return typedWrite<QFont>(src, dst);
case QMetaType::QVector2D:
- return typedWrite<QVector2D>(src, dst, dstSize);
+ return typedWrite<QVector2D>(src, dst);
case QMetaType::QVector3D:
- return typedWrite<QVector3D>(src, dst, dstSize);
+ return typedWrite<QVector3D>(src, dst);
case QMetaType::QVector4D:
- return typedWrite<QVector4D>(src, dst, dstSize);
+ return typedWrite<QVector4D>(src, dst);
case QMetaType::QQuaternion:
- return typedWrite<QQuaternion>(src, dst, dstSize);
+ return typedWrite<QQuaternion>(src, dst);
case QMetaType::QMatrix4x4:
- {
- if (dstSize >= sizeof(QMatrix4x4))
- return typedWrite<QMatrix4x4>(src, dst, dstSize);
-
- // special case: storing matrix into variant
- // eg, QVMEMO QVMEVariant data cell is big enough to store
- // QVariant, but not large enough to store QMatrix4x4.
- Q_ASSERT(dstSize >= sizeof(QVariant));
- const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
- QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
- QMatrix4x4 dstMatVal = dstMatVar->value<QMatrix4x4>();
- if (dstMatVal != *srcMat) {
- *dstMatVar = QVariant(*srcMat);
- return true;
- }
- return false;
- }
+ return typedWrite<QMatrix4x4>(src, dst);
default: break;
}
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index a231209cd0..5d492a4e75 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,71 @@ 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 for the job. You can use QQuickTextureFactory::textureFactoryForImage
+ if your provider works with QImage. The engine takes ownership of the returned QQuickTextureFactory.
+
+ \note This method will be called only when needed. For example, it may not be called if there is an
+ error or the job is cancelled. Therefore, allocate the QQuickTextureFactory instance only in this
+ method or otherwise ensure its deletion.
+ */
+
+
+/*!
\class QQuickImageProvider
\since 5.0
\inmodule QtQuick
@@ -213,7 +298,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 +308,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 +456,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 a1c9205539..0b7b5ce9a8 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
@@ -182,6 +171,7 @@ public:
virtual bool event(QEvent *e);
private slots:
void networkRequestDone();
+ void asyncResponseFinished();
private:
QQuickPixmapReader *reader;
};
@@ -206,8 +196,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;
@@ -221,7 +212,8 @@ private:
QNetworkAccessManager *networkAccessManager();
QNetworkAccessManager *accessManager;
- QHash<QNetworkReply*,QQuickPixmapReply*> replies;
+ QHash<QNetworkReply*,QQuickPixmapReply*> networkJobs;
+ QHash<QQuickImageResponse*,QQuickPixmapReply*> asyncResponses;
static int replyDownloadProgress;
static int replyFinished;
@@ -445,8 +437,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;
@@ -461,7 +453,7 @@ QQuickPixmapReader::~QQuickPixmapReader()
void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
{
- QQuickPixmapReply *job = replies.take(reply);
+ QQuickPixmapReply *job = networkJobs.take(reply);
if (job) {
job->redirectCount++;
@@ -478,7 +470,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;
}
}
@@ -500,7 +492,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();
@@ -509,6 +501,34 @@ 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 ? t->textureSize() : QSize(), t);
+ else
+ delete 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)
{
@@ -535,6 +555,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);
@@ -544,16 +570,23 @@ 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();
+ asyncResponse->deleteLater();
+ }
}
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url));
// deleteLater, since not owned by this thread
@@ -566,27 +599,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();
}
}
@@ -597,79 +637,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());
@@ -677,7 +735,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
@@ -688,7 +746,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);
}
}
}
@@ -781,8 +839,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
@@ -1091,7 +1147,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:
@@ -1099,9 +1155,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
@@ -1122,7 +1183,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());
@@ -1259,7 +1320,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/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index d9132a9cb2..77ffda474a 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -33,8 +33,7 @@
#include "qquickprofiler_p.h"
#include <QCoreApplication>
-#include <private/qqmldebugservice_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
QT_BEGIN_NAMESPACE
@@ -113,18 +112,22 @@ void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
qint64 QQuickProfiler::sendMessages(qint64 until, QList<QByteArray> &messages)
{
QMutexLocker lock(&m_dataMutex);
- while (next < m_data.size() && m_data[next].time <= until) {
- m_data[next++].toByteArrays(messages);
+ while (next < m_data.size()) {
+ if (m_data[next].time <= until)
+ m_data[next++].toByteArrays(messages);
+ else
+ return m_data[next].time;
}
- return next < m_data.size() ? m_data[next].time : -1;
+ m_data.clear();
+ next = 0;
+ return -1;
}
-void QQuickProfiler::initialize()
+void QQuickProfiler::initialize(QQmlProfilerService *service)
{
Q_ASSERT(s_instance == 0);
- QQmlProfilerService *service = QQmlProfilerService::instance();
s_instance = new QQuickProfiler(service);
- QQmlProfilerService::instance()->addGlobalProfiler(s_instance);
+ service->addGlobalProfiler(s_instance);
}
void animationTimerCallback(qint64 delta)
@@ -196,17 +199,12 @@ void QQuickProfiler::stopProfilingImpl()
{
QMutexLocker lock(&m_dataMutex);
featuresEnabled = 0;
- next = 0;
}
service->dataReady(this);
}
void QQuickProfiler::reportDataImpl()
{
- {
- QMutexLocker lock(&m_dataMutex);
- next = 0;
- }
service->dataReady(this);
}
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index aaed4bd60e..6b6e7fa062 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -318,7 +318,7 @@ public:
return featuresEnabled & (1 << QQuickProfiler::ProfileSceneGraph);
}
- static void initialize();
+ static void initialize(QQmlProfilerService *service);
virtual ~QQuickProfiler();
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 6ed32c10e2..c411207121 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/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/quick/util/qquickvalidator_p.h
index 942fb6e12c..59d7884afc 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
+++ b/src/quick/util/qquickvalidator_p.h
@@ -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 QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,47 +31,53 @@
**
****************************************************************************/
-#ifndef QTCPSERVERCONNECTION_H
-#define QTCPSERVERCONNECTION_H
+#ifndef QQUICKVALIDATOR_P_H
+#define QQUICKVALIDATOR_P_H
-#include <private/qqmldebugserverconnection_p.h>
+#include <QtGui/qvalidator.h>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
-class QQmlDebugServer;
-class QTcpServerConnectionPrivate;
-class QTcpServerConnection : public QObject, public QQmlDebugServerConnection
+#ifndef QT_NO_VALIDATOR
+class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QTcpServerConnection)
- Q_DISABLE_COPY(QTcpServerConnection)
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlDebugServerConnection")
- Q_INTERFACES(QQmlDebugServerConnection)
-
+ Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
public:
- QTcpServerConnection();
- ~QTcpServerConnection();
+ QQuickIntValidator(QObject *parent = 0);
- void setServer(QQmlDebugServer *server);
- bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress);
+ QString localeName() const;
+ void setLocaleName(const QString &name);
+ void resetLocaleName();
- bool isConnected() const;
- void send(const QList<QByteArray> &messages);
- void disconnect();
- bool waitForMessage();
+Q_SIGNALS:
+ void localeNameChanged();
+};
- bool listen();
- void waitForConnection();
+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);
-private Q_SLOTS:
- void readyRead();
- void newConnection();
- void invalidPacket();
+ QString localeName() const;
+ void setLocaleName(const QString &name);
+ void resetLocaleName();
-private:
- QTcpServerConnectionPrivate *d_ptr;
+Q_SIGNALS:
+ void localeNameChanged();
};
+#endif
QT_END_NAMESPACE
-#endif // QTCPSERVERCONNECTION_H
+#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.cpp b/src/quick/util/qquickvaluetypes.cpp
index fef6dfd1d0..1f0d54e4e7 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -533,6 +533,16 @@ void QQuickFontValueType::setFamily(const QString &family)
v.setFamily(family);
}
+QString QQuickFontValueType::styleName() const
+{
+ return v.styleName();
+}
+
+void QQuickFontValueType::setStyleName(const QString &style)
+{
+ v.setStyleName(style);
+}
+
bool QQuickFontValueType::bold() const
{
return v.bold();
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index f62306ed01..7a2e8888b7 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -266,10 +266,9 @@ class QQuickFontValueType
{
QFont v;
Q_GADGET
- Q_ENUMS(FontWeight)
- Q_ENUMS(Capitalization)
Q_PROPERTY(QString family READ family WRITE setFamily FINAL)
+ Q_PROPERTY(QString styleName READ styleName WRITE setStyleName FINAL)
Q_PROPERTY(bool bold READ bold WRITE setBold FINAL)
Q_PROPERTY(FontWeight weight READ weight WRITE setWeight FINAL)
Q_PROPERTY(bool italic READ italic WRITE setItalic FINAL)
@@ -292,17 +291,22 @@ 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;
QString family() const;
void setFamily(const QString &);
+ QString styleName() const;
+ void setStyleName(const QString &);
+
bool bold() const;
void setBold(bool b);
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..5755271fe1 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -39,8 +39,9 @@
#include "private/qquickitemchangelistener_p.h"
#include "private/qquickrendercontrol_p.h"
+#include <private/qqmldebugconnector_p.h>
#include <private/qquickprofiler_p.h>
-#include <private/qqmlinspectorservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <QtQml/qqmlengine.h>
@@ -95,8 +96,9 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
if (!engine.data()->incubationController())
engine.data()->setIncubationController(offscreenWindow->incubationController());
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->addView(q);
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->addView(q);
#ifndef QT_NO_DRAGANDDROP
q->setAcceptDrops(true);
@@ -142,13 +144,15 @@ QQuickWidgetPrivate::QQuickWidgetPrivate()
, eventPending(false)
, updatePending(false)
, fakeHidden(false)
+ , requestedSamples(0)
{
}
QQuickWidgetPrivate::~QQuickWidgetPrivate()
{
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->removeView(q_func());
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->removeView(q_func());
invalidateRenderControl();
@@ -538,6 +542,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 +566,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;
@@ -764,7 +775,7 @@ void QQuickWidget::createFramebufferObject()
context->makeCurrent(d->offscreenSurface);
- int samples = d->offscreenWindow->requestedFormat().samples();
+ int samples = d->requestedSamples;
if (!QOpenGLExtensions(context).hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
samples = 0;
@@ -878,14 +889,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;
}
@@ -1239,6 +1251,14 @@ void QQuickWidget::setFormat(const QSurfaceFormat &format)
newFormat.setDepthBufferSize(qMax(newFormat.depthBufferSize(), currentFormat.depthBufferSize()));
newFormat.setStencilBufferSize(qMax(newFormat.stencilBufferSize(), currentFormat.stencilBufferSize()));
newFormat.setAlphaBufferSize(qMax(newFormat.alphaBufferSize(), currentFormat.alphaBufferSize()));
+
+ // Do not include the sample count. Requesting a multisampled context is not necessary
+ // since we render into an FBO, never to an actual surface. What's more, attempting to
+ // create a pbuffer with a multisampled config crashes certain implementations. Just
+ // avoid the entire hassle, the result is the same.
+ d->requestedSamples = newFormat.samples();
+ newFormat.setSamples(0);
+
d->offscreenWindow->setFormat(newFormat);
}
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/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index e8d1f714f3..fa8bb3beb7 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -115,6 +115,8 @@ public:
bool eventPending;
bool updatePending;
bool fakeHidden;
+
+ int requestedSamples;
};
QT_END_NAMESPACE
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/bic/data/QtQuick.5.0.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtQuick.5.0.0.linux-gcc-amd64.txt
index 6c8ed16153..01f76a894f 100644
--- a/tests/auto/bic/data/QtQuick.5.0.0.linux-gcc-amd64.txt
+++ b/tests/auto/bic/data/QtQuick.5.0.0.linux-gcc-amd64.txt
@@ -7542,10 +7542,6 @@ Class QJSValueIterator
base size=8 base align=8
QJSValueIterator (0x0x7f49b0d69420) 0
-Class DesignerSupport
- size=8 align=8
- base size=8 base align=8
-DesignerSupport (0x0x7f49b0d69540) 0
Class QQuickTransform::QPrivateSignal
size=1 align=1
diff --git a/tests/auto/bic/data/QtQuick.5.1.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtQuick.5.1.0.linux-gcc-amd64.txt
index 4f970788e3..18ee25dccb 100644
--- a/tests/auto/bic/data/QtQuick.5.1.0.linux-gcc-amd64.txt
+++ b/tests/auto/bic/data/QtQuick.5.1.0.linux-gcc-amd64.txt
@@ -7864,10 +7864,6 @@ Class QJSValueIterator
base size=8 base align=8
QJSValueIterator (0x0x7fd8c4ff79c0) 0
-Class DesignerSupport
- size=8 align=8
- base size=8 base align=8
-DesignerSupport (0x0x7fd8c4ff7ae0) 0
Class QQuickTransform::QPrivateSignal
size=1 align=1
diff --git a/tests/auto/bic/data/QtQuick.5.2.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtQuick.5.2.0.linux-gcc-amd64.txt
index c652ca32d6..aa46b9ca87 100644
--- a/tests/auto/bic/data/QtQuick.5.2.0.linux-gcc-amd64.txt
+++ b/tests/auto/bic/data/QtQuick.5.2.0.linux-gcc-amd64.txt
@@ -8216,10 +8216,6 @@ QQmlPropertyMap (0x0x7f6f5eb9a4e0) 0
QObject (0x0x7f6f5e8cb060) 0
primary-for QQmlPropertyMap (0x0x7f6f5eb9a4e0)
-Class DesignerSupport
- size=8 align=8
- base size=8 base align=8
-DesignerSupport (0x0x7f6f5e8cb120) 0
Class QQuickTransform::QPrivateSignal
size=1 align=1
diff --git a/tests/auto/bic/data/QtQuick.5.3.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtQuick.5.3.0.linux-gcc-amd64.txt
index c268efa08c..080e8b9041 100644
--- a/tests/auto/bic/data/QtQuick.5.3.0.linux-gcc-amd64.txt
+++ b/tests/auto/bic/data/QtQuick.5.3.0.linux-gcc-amd64.txt
@@ -8247,11 +8247,6 @@ QQmlPropertyMap (0x0x7fc57b23ed68) 0
QObject (0x0x7fc57b1146c0) 0
primary-for QQmlPropertyMap (0x0x7fc57b23ed68)
-Class DesignerSupport
- size=8 align=8
- base size=8 base align=8
-DesignerSupport (0x0x7fc57b114780) 0
-
Class QQuickTransform::QPrivateSignal
size=1 align=1
base size=0 base align=1
diff --git a/tests/auto/bic/data/QtQuick.5.4.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtQuick.5.4.0.linux-gcc-amd64.txt
index e689193076..de684fa2f8 100644
--- a/tests/auto/bic/data/QtQuick.5.4.0.linux-gcc-amd64.txt
+++ b/tests/auto/bic/data/QtQuick.5.4.0.linux-gcc-amd64.txt
@@ -8549,11 +8549,6 @@ QQmlPropertyMap (0x0x7faeca8d9e38) 0
QObject (0x0x7faeca7bb780) 0
primary-for QQmlPropertyMap (0x0x7faeca8d9e38)
-Class DesignerSupport
- size=8 align=8
- base size=8 base align=8
-DesignerSupport (0x0x7faeca7bb840) 0
-
Class QQuickTransform::QPrivateSignal
size=1 align=1
base size=0 base align=1
diff --git a/tests/auto/bic/data/QtQuickWidgets.5.3.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtQuickWidgets.5.3.0.linux-gcc-amd64.txt
index 1b55d5e268..48409f49b7 100644
--- a/tests/auto/bic/data/QtQuickWidgets.5.3.0.linux-gcc-amd64.txt
+++ b/tests/auto/bic/data/QtQuickWidgets.5.3.0.linux-gcc-amd64.txt
@@ -8247,10 +8247,6 @@ QQmlPropertyMap (0x0x7f249928bd68) 0
QObject (0x0x7f2498d5f720) 0
primary-for QQmlPropertyMap (0x0x7f249928bd68)
-Class DesignerSupport
- size=8 align=8
- base size=8 base align=8
-DesignerSupport (0x0x7f2498d5f7e0) 0
Class QQuickTransform::QPrivateSignal
size=1 align=1
diff --git a/tests/auto/bic/data/QtQuickWidgets.5.4.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtQuickWidgets.5.4.0.linux-gcc-amd64.txt
index 93e620995e..57b4485857 100644
--- a/tests/auto/bic/data/QtQuickWidgets.5.4.0.linux-gcc-amd64.txt
+++ b/tests/auto/bic/data/QtQuickWidgets.5.4.0.linux-gcc-amd64.txt
@@ -8549,11 +8549,6 @@ QQmlPropertyMap (0x0x7f4037b54e38) 0
QObject (0x0x7f40376357e0) 0
primary-for QQmlPropertyMap (0x0x7f4037b54e38)
-Class DesignerSupport
- size=8 align=8
- base size=8 base align=8
-DesignerSupport (0x0x7f40376358a0) 0
-
Class QQuickTransform::QPrivateSignal
size=1 align=1
base size=0 base align=1
diff --git a/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp b/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp
index 325702f9c4..8132f3e24b 100644
--- a/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp
+++ b/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp
@@ -68,7 +68,7 @@ void tst_qquickpointattractor::test_basic()
QVERIFY(d->x != 0.f);
QVERIFY(d->y != 0.f);
- QVERIFY(d->x == d->y);
+ QCOMPARE(d->x, d->y);
QCOMPARE(d->vx, 0.f);
QCOMPARE(d->vy, 0.f);
QCOMPARE(d->ax, 0.f);
diff --git a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
index 21384ef3d8..92065d35e3 100644
--- a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
+++ b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
@@ -120,10 +120,10 @@ void tst_QPauseAnimationJob::changeDirectionWhileRunning()
animation.setDuration(400);
animation.start();
QTest::qWait(100);
- QVERIFY(animation.state() == QAbstractAnimationJob::Running);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Running);
animation.setDirection(QAbstractAnimationJob::Backward);
QTest::qWait(animation.totalDuration() + 50);
- QVERIFY(animation.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped);
}
void tst_QPauseAnimationJob::noTimerUpdates_data()
@@ -155,7 +155,7 @@ void tst_QPauseAnimationJob::noTimerUpdates()
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QVERIFY(animation.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped);
const int expectedLoopCount = 1 + loopCount;
#ifdef Q_OS_WIN
@@ -183,13 +183,13 @@ void tst_QPauseAnimationJob::multiplePauseAnimations()
if (animation.state() != QAbstractAnimationJob::Stopped)
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QVERIFY(animation.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped);
#ifdef Q_OS_WIN
if (animation2.state() != QAbstractAnimationJob::Running)
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QVERIFY(animation2.state() == QAbstractAnimationJob::Running);
+ QCOMPARE(animation2.state(), QAbstractAnimationJob::Running);
#ifdef Q_OS_WIN
if (animation.m_updateCurrentTimeCount != 2)
@@ -224,7 +224,7 @@ void tst_QPauseAnimationJob::pauseAndPropertyAnimations()
QCOMPARE(animation.state(), QAbstractAnimationJob::Running);
QTRY_COMPARE(animation.state(), QAbstractAnimationJob::Running);
- QVERIFY(pause.state() == QAbstractAnimationJob::Running);
+ QCOMPARE(pause.state(), QAbstractAnimationJob::Running);
QVERIFY2(pause.m_updateCurrentTimeCount >= 2,
QByteArrayLiteral("pause.m_updateCurrentTimeCount=") + QByteArray::number(pause.m_updateCurrentTimeCount));
@@ -245,7 +245,7 @@ void tst_QPauseAnimationJob::pauseResume()
QCOMPARE(animation.state(), QAbstractAnimationJob::Paused);
animation.start();
QTest::qWait(300);
- QTRY_VERIFY(animation.state() == QAbstractAnimationJob::Stopped);
+ QTRY_COMPARE(animation.state(), QAbstractAnimationJob::Stopped);
QVERIFY2(animation.m_updateCurrentTimeCount >= 3,
QByteArrayLiteral("animation.m_updateCurrentTimeCount=") + QByteArray::number(animation.m_updateCurrentTimeCount));
}
@@ -266,39 +266,39 @@ void tst_QPauseAnimationJob::sequentialPauseGroup()
QCOMPARE(animation2.m_updateCurrentTimeCount, 0);
QCOMPARE(animation3.m_updateCurrentTimeCount, 0);
- QVERIFY(group.state() == QAbstractAnimationJob::Running);
- QVERIFY(animation1.state() == QAbstractAnimationJob::Running);
- QVERIFY(animation2.state() == QAbstractAnimationJob::Stopped);
- QVERIFY(animation3.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(animation1.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(animation2.state(), QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation3.state(), QAbstractAnimationJob::Stopped);
group.setCurrentTime(250);
QCOMPARE(animation1.m_updateCurrentTimeCount, 2);
QCOMPARE(animation2.m_updateCurrentTimeCount, 1);
QCOMPARE(animation3.m_updateCurrentTimeCount, 0);
- QVERIFY(group.state() == QAbstractAnimationJob::Running);
- QVERIFY(animation1.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(animation1.state(), QAbstractAnimationJob::Stopped);
QCOMPARE((QAbstractAnimationJob*)&animation2, group.currentAnimation());
- QVERIFY(animation2.state() == QAbstractAnimationJob::Running);
- QVERIFY(animation3.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation2.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(animation3.state(), QAbstractAnimationJob::Stopped);
group.setCurrentTime(500);
QCOMPARE(animation1.m_updateCurrentTimeCount, 2);
QCOMPARE(animation2.m_updateCurrentTimeCount, 2);
QCOMPARE(animation3.m_updateCurrentTimeCount, 1);
- QVERIFY(group.state() == QAbstractAnimationJob::Running);
- QVERIFY(animation1.state() == QAbstractAnimationJob::Stopped);
- QVERIFY(animation2.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(animation1.state(), QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation2.state(), QAbstractAnimationJob::Stopped);
QCOMPARE((QAbstractAnimationJob*)&animation3, group.currentAnimation());
- QVERIFY(animation3.state() == QAbstractAnimationJob::Running);
+ QCOMPARE(animation3.state(), QAbstractAnimationJob::Running);
group.setCurrentTime(750);
- QVERIFY(group.state() == QAbstractAnimationJob::Stopped);
- QVERIFY(animation1.state() == QAbstractAnimationJob::Stopped);
- QVERIFY(animation2.state() == QAbstractAnimationJob::Stopped);
- QVERIFY(animation3.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation1.state(), QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation2.state(), QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation3.state(), QAbstractAnimationJob::Stopped);
QCOMPARE(animation1.m_updateCurrentTimeCount, 2);
QCOMPARE(animation2.m_updateCurrentTimeCount, 2);
@@ -318,22 +318,22 @@ void tst_QPauseAnimationJob::sequentialGroupWithPause()
group.start();
- QVERIFY(group.state() == QAbstractAnimationJob::Running);
- QVERIFY(animation.state() == QAbstractAnimationJob::Running);
- QVERIFY(pause.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(pause.state(), QAbstractAnimationJob::Stopped);
group.setCurrentTime(300);
- QVERIFY(group.state() == QAbstractAnimationJob::Running);
- QVERIFY(animation.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped);
QCOMPARE((QAbstractAnimationJob*)&pause, group.currentAnimation());
- QVERIFY(pause.state() == QAbstractAnimationJob::Running);
+ QCOMPARE(pause.state(), QAbstractAnimationJob::Running);
group.setCurrentTime(600);
- QVERIFY(group.state() == QAbstractAnimationJob::Stopped);
- QVERIFY(animation.state() == QAbstractAnimationJob::Stopped);
- QVERIFY(pause.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped);
+ QCOMPARE(pause.state(), QAbstractAnimationJob::Stopped);
QCOMPARE(pause.m_updateCurrentTimeCount, 2);
}
@@ -383,11 +383,11 @@ void tst_QPauseAnimationJob::multipleSequentialGroups()
group.start();
- QVERIFY(group.state() == QAbstractAnimationJob::Running);
- QVERIFY(subgroup1.state() == QAbstractAnimationJob::Running);
- QVERIFY(subgroup2.state() == QAbstractAnimationJob::Running);
- QVERIFY(subgroup3.state() == QAbstractAnimationJob::Running);
- QVERIFY(subgroup4.state() == QAbstractAnimationJob::Running);
+ QCOMPARE(group.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(subgroup1.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(subgroup2.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(subgroup3.state(), QAbstractAnimationJob::Running);
+ QCOMPARE(subgroup4.state(), QAbstractAnimationJob::Running);
// This is a pretty long animation so it tends to get rather out of sync
// when using the consistent timer, so run for an extra half second for good
@@ -398,31 +398,31 @@ void tst_QPauseAnimationJob::multipleSequentialGroups()
if (group.state() != QAbstractAnimationJob::Stopped)
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QTRY_VERIFY(group.state() == QAbstractAnimationJob::Stopped);
+ QTRY_COMPARE(group.state(), QAbstractAnimationJob::Stopped);
#ifdef Q_OS_WIN
if (subgroup1.state() != QAbstractAnimationJob::Stopped)
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QVERIFY(subgroup1.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(subgroup1.state(), QAbstractAnimationJob::Stopped);
#ifdef Q_OS_WIN
if (subgroup2.state() != QAbstractAnimationJob::Stopped)
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QVERIFY(subgroup2.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(subgroup2.state(), QAbstractAnimationJob::Stopped);
#ifdef Q_OS_WIN
if (subgroup3.state() != QAbstractAnimationJob::Stopped)
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QVERIFY(subgroup3.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(subgroup3.state(), QAbstractAnimationJob::Stopped);
#ifdef Q_OS_WIN
if (subgroup4.state() != QAbstractAnimationJob::Stopped)
QEXPECT_FAIL("", winTimerError, Abort);
#endif
- QVERIFY(subgroup4.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(subgroup4.state(), QAbstractAnimationJob::Stopped);
#ifdef Q_OS_WIN
if (pause5.m_updateCurrentTimeCount != 4)
@@ -437,7 +437,7 @@ void tst_QPauseAnimationJob::zeroDuration()
animation.setDuration(0);
animation.start();
QTest::qWait(animation.totalDuration() + 100);
- QVERIFY(animation.state() == QAbstractAnimationJob::Stopped);
+ QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped);
QCOMPARE(animation.m_updateCurrentTimeCount, 1);
}
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/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
index 848bec0b0b..f004593d94 100644
--- a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
@@ -911,7 +911,7 @@ void tst_QSequentialAnimationGroupJob::startDelay()
QTest::qWait(500);
QTRY_COMPARE(group.state(), QAnimationGroupJob::Stopped);
- QVERIFY(group.currentLoopTime() == 375);
+ QCOMPARE(group.currentLoopTime(), 375);
}
void tst_QSequentialAnimationGroupJob::clearGroup()
@@ -1456,7 +1456,7 @@ void tst_QSequentialAnimationGroupJob::addRemoveAnimation()
void tst_QSequentialAnimationGroupJob::currentAnimation()
{
QSequentialAnimationGroupJob group;
- QVERIFY(group.currentAnimation() == 0);
+ QVERIFY(!group.currentAnimation());
TestAnimation anim(0);
group.appendAnimation(&anim);
@@ -1466,7 +1466,7 @@ void tst_QSequentialAnimationGroupJob::currentAnimation()
void tst_QSequentialAnimationGroupJob::currentAnimationWithZeroDuration()
{
QSequentialAnimationGroupJob group;
- QVERIFY(group.currentAnimation() == 0);
+ QVERIFY(!group.currentAnimation());
TestAnimation zero1(0);
TestAnimation zero2(0);
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/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
index 6f559d7833..d0801dd4ee 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
+++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
@@ -185,7 +185,7 @@ void tst_QDebugMessageService::init()
if (m_client->state() != QQmlDebugClient::Enabled)
QQmlDebugTest::waitForSignal(m_client, SIGNAL(enabled()));
- QVERIFY(m_client->state() == QQmlDebugClient::Enabled);
+ QCOMPARE(m_client->state(), QQmlDebugClient::Enabled);
}
void tst_QDebugMessageService::cleanup()
diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
index 155f11bdaf..db9e621d54 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
+++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -222,7 +222,7 @@ void tst_QPacketProtocol::read()
void tst_QPacketProtocol::device()
{
QPacketProtocol p(m_client);
- QVERIFY(p.device() == m_client);
+ QCOMPARE(p.device(), m_client);
}
void tst_QPacketProtocol::tst_QPacket_clear()
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index 7ca69b6d44..6fc6c6a914 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -42,6 +42,8 @@
#include "debugutil_p.h"
#include "qqmldebugtestservice.h"
+#include <private/qqmldebugconnector_p.h>
+
#define PORT 13770
#define STR_PORT "13770"
@@ -51,6 +53,7 @@ class tst_QQmlDebugClient : public QObject
private:
QQmlDebugConnection *m_conn;
+ QQmlDebugTestService *m_service;
private slots:
void initTestCase();
@@ -64,26 +67,31 @@ private slots:
void tst_QQmlDebugClient::initTestCase()
{
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QTest::ignoreMessage(QtWarningMsg,
+ "QML debugger: Cannot set plugin key after loading the plugin.");
+
+ m_service = new QQmlDebugTestService("tst_QQmlDebugClient::handshake()");
const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT);
QTest::ignoreMessage(QtDebugMsg, waitingMsg.toLatin1().constData());
+ QQmlDebuggingEnabler::startTcpDebugServer(PORT);
+
new QQmlEngine(this);
m_conn = new QQmlDebugConnection(this);
QQmlDebugTestClient client("tst_QQmlDebugClient::handshake()", m_conn);
- QQmlDebugTestService service("tst_QQmlDebugClient::handshake()");
+
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());
- QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
}
@@ -107,14 +115,6 @@ void tst_QQmlDebugClient::state()
QQmlDebugTestClient client("tst_QQmlDebugClient::state()", m_conn);
QCOMPARE(client.state(), QQmlDebugClient::Unavailable);
- {
- QQmlDebugTestService service("tst_QQmlDebugClient::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_QQmlDebugClient::state()\"");
QQmlDebugClient client2("tst_QQmlDebugClient::state()", m_conn);
@@ -126,8 +126,7 @@ void tst_QQmlDebugClient::state()
void tst_QQmlDebugClient::sendMessage()
{
- QQmlDebugTestService service("tst_QQmlDebugClient::sendMessage()");
- QQmlDebugTestClient client("tst_QQmlDebugClient::sendMessage()", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugClient::handshake()", m_conn);
QByteArray msg = "hello!";
@@ -153,7 +152,6 @@ void tst_QQmlDebugClient::sequentialConnect()
{
QQmlDebugConnection connection2;
QQmlDebugTestClient client2("tst_QQmlDebugClient::handshake()", &connection2);
- QQmlDebugTestService service("tst_QQmlDebugClient::handshake()");
m_conn->close();
QVERIFY(!m_conn->isConnected());
@@ -165,23 +163,10 @@ void tst_QQmlDebugClient::sequentialConnect()
connection2.connectToHost("127.0.0.1", PORT);
QVERIFY(connection2.waitForConnected());
QVERIFY(connection2.isConnected());
- QTRY_VERIFY(client2.state() == QQmlDebugClient::Enabled);
+ QTRY_COMPARE(client2.state(), QQmlDebugClient::Enabled);
}
-int main(int argc, char *argv[])
-{
- int _argc = argc + 1;
- char **_argv = new char*[_argc];
- for (int i = 0; i < argc; ++i)
- _argv[i] = argv[i];
- char arg[] = "-qmljsdebugger=port:" STR_PORT;
- _argv[_argc - 1] = arg;
-
- QGuiApplication app(_argc, _argv);
- tst_QQmlDebugClient tc;
- return QTest::qExec(&tc, _argc, _argv);
- delete _argv;
-}
+QTEST_MAIN(tst_QQmlDebugClient)
#include "tst_qqmldebugclient.moc"
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index ed424b5a67..7dbe35807d 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -120,6 +120,8 @@ const char *UNCAUGHT = "uncaught";
const char *BLOCKMODE = "-qmljsdebugger=port:3771,3800,block";
const char *NORMALMODE = "-qmljsdebugger=port:3771,3800";
+const char *BLOCKRESTRICTEDMODE = "-qmljsdebugger=port:3771,3800,block,services:V8Debugger";
+const char *NORMALRESTRICTEDMODE = "-qmljsdebugger=port:3771,3800,services:V8Debugger";
const char *TEST_QMLFILE = "test.qml";
const char *TEST_JSFILE = "test.js";
const char *TIMER_QMLFILE = "timer.qml";
@@ -157,7 +159,8 @@ class tst_QQmlDebugJS : public QQmlDataTest
{
Q_OBJECT
- bool init(const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true);
+ void init(const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true,
+ bool restrictServices = false);
private slots:
void initTestCase();
@@ -165,6 +168,7 @@ private slots:
void cleanup();
+ void connect_data();
void connect();
void interrupt();
void getVersion();
@@ -822,33 +826,29 @@ void tst_QQmlDebugJS::cleanupTestCase()
// qDebug() << "Time Elapsed:" << t.elapsed();
}
-bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode)
+void tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode, bool restrictServices)
{
connection = new QQmlDebugConnection();
process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this);
client = new QJSDebugClient(connection);
+ const char *args = 0;
if (blockMode)
- process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile));
+ args = restrictServices ? BLOCKRESTRICTEDMODE : BLOCKMODE;
else
- process->start(QStringList() << QLatin1String(NORMALMODE) << testFile(qmlFile));
+ args = restrictServices ? NORMALRESTRICTEDMODE : NORMALMODE;
- if (!process->waitForSessionStart()) {
- qDebug() << "could not launch application, or did not get 'Waiting for connection'.";
- return false;
- }
+ process->start(QStringList() << QLatin1String(args) << testFile(qmlFile));
+
+ QVERIFY(process->waitForSessionStart());
const int port = process->debugPort();
connection->connectToHost("127.0.0.1", port);
- if (!connection->waitForConnected()) {
- qDebug() << "could not connect to host!";
- return false;
- }
+ QVERIFY(connection->waitForConnected());
- if (client->state() == QQmlDebugClient::Enabled)
- return true;
- return QQmlDebugTest::waitForSignal(client, SIGNAL(enabled()));
+ if (client->state() != QQmlDebugClient::Enabled)
+ QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(enabled())));
}
void tst_QQmlDebugJS::cleanup()
@@ -874,11 +874,21 @@ void tst_QQmlDebugJS::cleanup()
connection = 0;
}
-void tst_QQmlDebugJS::connect()
+void tst_QQmlDebugJS::connect_data()
{
- //void connect()
+ QTest::addColumn<bool>("blockMode");
+ QTest::addColumn<bool>("restrictMode");
+ QTest::newRow("normal/unrestricted") << false << false;
+ QTest::newRow("block/unrestricted") << true << false;
+ QTest::newRow("normal/restricted") << false << true;
+ QTest::newRow("block/restricted") << true << true;
+}
- QVERIFY(init());
+void tst_QQmlDebugJS::connect()
+{
+ QFETCH(bool, blockMode);
+ QFETCH(bool, restrictMode);
+ init(QString(TEST_QMLFILE), blockMode, restrictMode);
client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
}
@@ -887,7 +897,7 @@ void tst_QQmlDebugJS::interrupt()
{
//void connect()
- QVERIFY(init());
+ init();
client->connect();
client->interrupt();
@@ -898,7 +908,7 @@ void tst_QQmlDebugJS::getVersion()
{
//void version()
- QVERIFY(init());
+ init();
client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
@@ -923,7 +933,7 @@ void tst_QQmlDebugJS::disconnect()
{
//void disconnect()
- QVERIFY(init());
+ init();
client->connect();
client->disconnect();
@@ -935,7 +945,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted()
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
int sourceLine = 39;
- QVERIFY(init(ONCOMPLETED_QMLFILE));
+ init(ONCOMPLETED_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -955,7 +965,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
int sourceLine = 39;
- QVERIFY(init(CREATECOMPONENT_QMLFILE));
+ init(CREATECOMPONENT_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -973,7 +983,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
{
int sourceLine = 40;
- QVERIFY(init(TIMER_QMLFILE));
+ init(TIMER_QMLFILE);
client->connect();
//We can set the breakpoint after connect() here because the timer is repeating and if we miss
@@ -995,7 +1005,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
int sourceLine = 35;
- QVERIFY(init(LOADJSFILE_QMLFILE));
+ init(LOADJSFILE_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
client->connect();
@@ -1016,7 +1026,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
int sourceLine = 39;
int actualLine = 41;
- QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
+ init(BREAKPOINTRELOCATION_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1038,7 +1048,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
int sourceLine = 40;
int actualLine = 41;
- QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
+ init(BREAKPOINTRELOCATION_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1059,7 +1069,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
int sourceLine = 44;
- QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
+ init(BREAKPOINTRELOCATION_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1078,7 +1088,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
{
int out = 10;
int sourceLine = 42;
- QVERIFY(init(CONDITION_QMLFILE));
+ init(CONDITION_QMLFILE);
client->connect();
//The breakpoint is in a timer loop so we can set it after connect().
@@ -1112,7 +1122,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
void tst_QQmlDebugJS::setBreakpointInScriptThatQuits()
{
- QVERIFY(init(QUIT_QMLFILE));
+ init(QUIT_QMLFILE);
int sourceLine = 41;
@@ -1153,7 +1163,7 @@ void tst_QQmlDebugJS::setBreakpointOnEvent()
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
- QVERIFY(init(TIMER_QMLFILE));
+ init(TIMER_QMLFILE);
client->setBreakpoint(QLatin1String(EVENT), QLatin1String("triggered"), -1, -1, true);
client->connect();
@@ -1174,7 +1184,7 @@ void tst_QQmlDebugJS::clearBreakpoint()
int sourceLine1 = 42;
int sourceLine2 = 43;
- QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
+ init(CHANGEBREAKPOINT_QMLFILE);
client->connect();
//The breakpoints are in a timer loop so we can set them after connect().
@@ -1219,7 +1229,7 @@ void tst_QQmlDebugJS::setExceptionBreak()
{
//void setExceptionBreak(QString type, bool enabled = false);
- QVERIFY(init(EXCEPTION_QMLFILE));
+ init(EXCEPTION_QMLFILE);
client->setExceptionBreak(QJSDebugClient::All,true);
client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
@@ -1230,7 +1240,7 @@ void tst_QQmlDebugJS::stepNext()
//void continueDebugging(StepAction stepAction, int stepCount = 1);
int sourceLine = 42;
- QVERIFY(init(STEPACTION_QMLFILE));
+ init(STEPACTION_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1254,7 +1264,7 @@ void tst_QQmlDebugJS::stepIn()
int sourceLine = 46;
int actualLine = 42;
- QVERIFY(init(STEPACTION_QMLFILE));
+ init(STEPACTION_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
client->connect();
@@ -1278,7 +1288,7 @@ void tst_QQmlDebugJS::stepOut()
int sourceLine = 42;
int actualLine = 46;
- QVERIFY(init(STEPACTION_QMLFILE));
+ init(STEPACTION_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1302,7 +1312,7 @@ void tst_QQmlDebugJS::continueDebugging()
int sourceLine1 = 46;
int sourceLine2 = 43;
- QVERIFY(init(STEPACTION_QMLFILE));
+ init(STEPACTION_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true);
@@ -1326,7 +1336,7 @@ void tst_QQmlDebugJS::backtrace()
//void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
int sourceLine = 39;
- QVERIFY(init(ONCOMPLETED_QMLFILE));
+ init(ONCOMPLETED_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1341,7 +1351,7 @@ void tst_QQmlDebugJS::getFrameDetails()
//void frame(int number = -1);
int sourceLine = 39;
- QVERIFY(init(ONCOMPLETED_QMLFILE));
+ init(ONCOMPLETED_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1356,7 +1366,7 @@ void tst_QQmlDebugJS::getScopeDetails()
//void scope(int number = -1, int frameNumber = -1);
int sourceLine = 39;
- QVERIFY(init(ONCOMPLETED_QMLFILE));
+ init(ONCOMPLETED_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1371,7 +1381,7 @@ void tst_QQmlDebugJS::evaluateInGlobalScope()
{
//void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
- QVERIFY(init());
+ init();
client->connect();
client->evaluate(QLatin1String("console.log('Hello World')"), true);
@@ -1393,7 +1403,7 @@ void tst_QQmlDebugJS::evaluateInLocalScope()
//void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
int sourceLine = 47;
- QVERIFY(init(ONCOMPLETED_QMLFILE));
+ init(ONCOMPLETED_QMLFILE);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
client->connect();
@@ -1427,7 +1437,7 @@ void tst_QQmlDebugJS::getScripts()
{
//void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
- QVERIFY(init());
+ init();
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QString(TEST_QMLFILE), 40, -1, true);
client->connect();
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..0343ea77ee
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** 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"
+
+#include <private/qqmldebugconnector_p.h>
+
+QString fileName;
+
+class tst_QQmlDebugLocal : public QObject
+{
+ Q_OBJECT
+
+private:
+ QQmlDebugConnection *m_conn;
+ QQmlDebugTestService *m_service;
+
+ bool connect();
+
+signals:
+ void waiting();
+ void parallel();
+
+private slots:
+ void initTestCase();
+
+ void name();
+ void state();
+ void sendMessage();
+};
+
+void tst_QQmlDebugLocal::initTestCase()
+{
+ fileName = QString::fromLatin1("tst_QQmlDebugLocal%1").arg(std::time(0));
+ QQmlDebugConnector::setPluginKey("QQmlDebugServer");
+ QTest::ignoreMessage(QtWarningMsg,
+ "QML debugger: Cannot set plugin key after loading the plugin.");
+ m_service = new QQmlDebugTestService("tst_QQmlDebugLocal::handshake()");
+
+ 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);
+
+ QQmlDebuggingEnabler::connectToLocalDebugger(fileName);
+
+ new QQmlEngine(this);
+
+ QQmlDebugTestClient client("tst_QQmlDebugLocal::handshake()", m_conn);
+
+ for (int i = 0; i < 50; ++i) {
+ // try for 5 seconds ...
+ if (m_conn->waitForConnected(100))
+ break;
+ }
+
+ QVERIFY(m_conn->isConnected());
+
+ 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);
+
+ // 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()
+{
+ QQmlDebugTestClient client("tst_QQmlDebugLocal::handshake()", m_conn);
+
+ QByteArray msg = "hello!";
+
+ QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
+
+ client.sendMessage(msg);
+ QByteArray resp = client.waitForResponse();
+ QCOMPARE(resp, msg);
+}
+
+QTEST_MAIN(tst_QQmlDebugLocal)
+
+#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..b63c5c0a6d 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -44,6 +44,7 @@
#include "debugutil_p.h"
#include "qqmldebugclient.h"
#include "qqmldebugtestservice.h"
+#include <private/qqmldebugconnector_p.h>
#define PORT 3769
#define STR_PORT "3769"
@@ -53,7 +54,7 @@ class tst_QQmlDebugService : public QQmlDataTest
Q_OBJECT
private:
QQmlDebugConnection *m_conn;
-
+ QQmlDebugTestService *m_service;
private slots:
@@ -65,7 +66,6 @@ private slots:
void sendMessage();
void idForObject();
void objectForId();
- void objectToString();
void checkSupportForDataStreamVersion();
void checkSupportForOldDataStreamVersion();
};
@@ -73,8 +73,15 @@ private slots:
void tst_QQmlDebugService::initTestCase()
{
QQmlDataTest::initTestCase();
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QTest::ignoreMessage(QtWarningMsg,
+ "QML debugger: Cannot set plugin key after loading the plugin.");
+ m_service = new QQmlDebugTestService("tst_QQmlDebugService", 2);
+
const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT);
QTest::ignoreMessage(QtDebugMsg, waitingMsg.toLatin1().constData());
+ QQmlDebuggingEnabler::startTcpDebugServer(PORT);
+
new QQmlEngine(this);
m_conn = new QQmlDebugConnection(this);
@@ -87,8 +94,6 @@ void tst_QQmlDebugService::initTestCase()
QTest::qSleep(100);
}
QVERIFY(m_conn->isConnected());
-
- QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
}
void tst_QQmlDebugService::checkPortRange()
@@ -128,67 +133,64 @@ void tst_QQmlDebugService::checkPortRange()
void tst_QQmlDebugService::name()
{
- QString name = "tst_QQmlDebugService::name()";
-
- QQmlDebugService service(name, 1);
- QCOMPARE(service.name(), name);
+ QCOMPARE(m_service->name(), QLatin1String("tst_QQmlDebugService"));
}
void tst_QQmlDebugService::version()
{
- QString name = "tst_QQmlDebugService::name()";
-
- QQmlDebugService service(name, 2);
- QCOMPARE(service.version(), 2.0f);
+ QCOMPARE(m_service->version(), 2.0f);
}
void tst_QQmlDebugService::state()
{
- QQmlDebugTestService service("tst_QQmlDebugService::state()");
- QCOMPARE(service.state(), QQmlDebugService::Unavailable);
+ QCOMPARE(m_service->state(), QQmlDebugService::Unavailable);
{
- QQmlDebugTestClient client("tst_QQmlDebugService::state()", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
- QTRY_COMPARE(service.state(), QQmlDebugService::Enabled);
+ QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled);
}
+ QTRY_COMPARE(m_service->state(), QQmlDebugService::Unavailable);
- QTRY_COMPARE(service.state(), QQmlDebugService::Unavailable);
-
- QTest::ignoreMessage(QtWarningMsg, "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService::state()\"");
- QQmlDebugTestService duplicate("tst_QQmlDebugService::state()");
+ // We can do this because it will never addService()
+ QTest::ignoreMessage(QtWarningMsg,
+ "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService\"");
+ QQmlDebugTestService duplicate("tst_QQmlDebugService");
QCOMPARE(duplicate.state(), QQmlDebugService::NotConnected);
+ QTest::ignoreMessage(QtWarningMsg,
+ "QQmlDebugService: Plugin \"tst_QQmlDebugService\" is not registered.");
}
void tst_QQmlDebugService::sendMessage()
{
- QQmlDebugTestService service("tst_QQmlDebugService::sendMessage()");
- QQmlDebugTestClient client("tst_QQmlDebugService::sendMessage()", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
QByteArray msg = "hello!";
QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
- QTRY_COMPARE(service.state(), QQmlDebugService::Enabled);
+ QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled);
client.sendMessage(msg);
QByteArray resp = client.waitForResponse();
QCOMPARE(resp, msg);
- QTest::ignoreMessage(QtWarningMsg, "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService::sendMessage()\"");
- QQmlDebugTestService duplicate("tst_QQmlDebugService::sendMessage()");
- duplicate.sendMessage("msg");
+ QTest::ignoreMessage(QtWarningMsg,
+ "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService\"");
+ QQmlDebugTestService duplicate("tst_QQmlDebugService");
+ emit duplicate.messageToClient(duplicate.name(), "msg");
+ QTest::ignoreMessage(QtWarningMsg,
+ "QQmlDebugService: Plugin \"tst_QQmlDebugService\" is not registered.");
}
void tst_QQmlDebugService::checkSupportForDataStreamVersion()
{
- QQmlDebugTestService service("tst_QQmlDebugService::sendMessage2()");
- QQmlDebugTestClient client("tst_QQmlDebugService::sendMessage2()", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
QByteArray msg = "hello!";
QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
- QTRY_COMPARE(service.state(), QQmlDebugService::Enabled);
+ QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled);
client.sendMessage(msg);
QByteArray resp = client.waitForResponse();
@@ -231,18 +233,6 @@ void tst_QQmlDebugService::objectForId()
QCOMPARE(QQmlDebugService::objectForId(id), static_cast<QObject*>(0));
}
-void tst_QQmlDebugService::objectToString()
-{
- QCOMPARE(QQmlDebugService::objectToString(0), QString("NULL"));
-
- QObject *obj = new QObject;
- QCOMPARE(QQmlDebugService::objectToString(obj), QString("QObject: <unnamed>"));
-
- obj->setObjectName("Hello");
- QCOMPARE(QQmlDebugService::objectToString(obj), QString("QObject: Hello"));
- delete obj;
-}
-
void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
{
//create a new connection;
@@ -258,14 +248,12 @@ void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
}
QVERIFY(m_conn->isConnected());
- QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
- QQmlDebugTestService service("tst_QQmlDebugService::sendMessage2()");
- QQmlDebugTestClient client("tst_QQmlDebugService::sendMessage2()", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
QByteArray msg = "hello!";
QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
- QTRY_COMPARE(service.state(), QQmlDebugService::Enabled);
+ QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled);
client.sendMessage(msg);
QByteArray resp = client.waitForResponse();
@@ -273,20 +261,6 @@ void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
QCOMPARE(m_conn->dataStreamVersion(), int(QDataStream::Qt_4_7));
}
-
-int main(int argc, char *argv[])
-{
- int _argc = argc + 1;
- char **_argv = new char*[_argc];
- for (int i = 0; i < argc; ++i)
- _argv[i] = argv[i];
- char arg[] = "-qmljsdebugger=port:" STR_PORT ",host:127.0.0.1";
- _argv[_argc - 1] = arg;
-
- QGuiApplication app(_argc, _argv);
- tst_QQmlDebugService tc;
- return QTest::qExec(&tc, _argc, _argv);
- delete _argv;
-}
+QTEST_MAIN(tst_QQmlDebugService)
#include "tst_qqmldebugservice.moc"
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
index f6cf9dae60..11fa56d710 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
@@ -103,12 +103,15 @@ private:
QQmlDebugConnection *m_connection;
QQmlEngineControlClient *m_client;
- void connect(const QString &testFile);
+ void connect(const QString &testFile, bool restrictServices);
+ void engine_data();
private slots:
void cleanup();
+ void startEngine_data();
void startEngine();
+ void stopEngine_data();
void stopEngine();
};
@@ -148,11 +151,13 @@ void QQmlEngineControlClient::messageReceived(const QByteArray &message)
QVERIFY(stream.atEnd());
}
-void tst_QQmlEngineControl::connect(const QString &testFile)
+void tst_QQmlEngineControl::connect(const QString &testFile, bool restrictServices)
{
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
QStringList arguments;
- arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block");
+ arguments << QString::fromLatin1("-qmljsdebugger=port:%1,%2,block%3")
+ .arg(STR_PORT_FROM).arg(STR_PORT_TO)
+ .arg(restrictServices ? QStringLiteral(",services:EngineControl") : QString());
arguments << QQmlDataTest::instance()->testFile(testFile);
@@ -165,6 +170,8 @@ void tst_QQmlEngineControl::connect(const QString &testFile)
const int port = m_process->debugPort();
m_connection->connectToHost(QLatin1String("127.0.0.1"), port);
+
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
}
void tst_QQmlEngineControl::cleanup()
@@ -183,11 +190,23 @@ void tst_QQmlEngineControl::cleanup()
m_connection = 0;
}
+void tst_QQmlEngineControl::engine_data()
+{
+ QTest::addColumn<bool>("restrictMode");
+ QTest::newRow("unrestricted") << false;
+ QTest::newRow("restricted") << true;
+}
+
+void tst_QQmlEngineControl::startEngine_data()
+{
+ engine_data();
+}
+
void tst_QQmlEngineControl::startEngine()
{
- connect("test.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+ QFETCH(bool, restrictMode);
+
+ connect("test.qml", restrictMode);
QTRY_VERIFY(!m_client->startingEngines.empty());
m_client->command(QQmlEngineControlClient::StartWaitingEngine, m_client->startingEngines.last());
@@ -196,11 +215,16 @@ void tst_QQmlEngineControl::startEngine()
"No engine start message received in time.");
}
+void tst_QQmlEngineControl::stopEngine_data()
+{
+ engine_data();
+}
+
void tst_QQmlEngineControl::stopEngine()
{
- connect("exit.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+ QFETCH(bool, restrictMode);
+
+ connect("exit.qml", restrictMode);
QTRY_VERIFY(!m_client->startingEngines.empty());
m_client->command(QQmlEngineControlClient::StartWaitingEngine, m_client->startingEngines.last());
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
index 8d119a30d7..0285bae189 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
@@ -61,6 +61,7 @@ public:
private:
+ void init(bool restrictServices);
QmlDebugObjectReference findRootObject();
QQmlDebugProcess *m_process;
@@ -68,9 +69,9 @@ private:
QQmlEngineDebugClient *m_engineDebugClient;
private slots:
- void init();
void cleanup();
+ void connect_data();
void connect();
void clearObjectReferenceHashonReloadQml();
};
@@ -93,9 +94,12 @@ QmlDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRootObject(
}
-void tst_QQmlEngineDebugInspectorIntegration::init()
+void tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
{
- const QString argument = "-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block";
+ const QString argument = QString::fromLatin1("-qmljsdebugger=port:%1,%2,block%3")
+ .arg(STR_PORT_FROM).arg(STR_PORT_TO)
+ .arg(restrictServices ? QStringLiteral(",services:QmlDebugger,QmlInspector") :
+ QString());
// ### Still using qmlscene because of QTBUG-33376
m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath)
@@ -108,10 +112,8 @@ void tst_QQmlEngineDebugInspectorIntegration::init()
m_inspectorClient = new QQmlInspectorClient(m_connection);
m_engineDebugClient = new QQmlEngineDebugClient(m_connection);
- const int port = m_process->debugPort();
- m_connection->connectToHost(QLatin1String("127.0.0.1"), port);
- bool ok = m_connection->waitForConnected();
- QVERIFY(ok);
+ m_connection->connectToHost(QLatin1String("127.0.0.1"), m_process->debugPort());
+ QVERIFY(m_connection->waitForConnected());
}
void tst_QQmlEngineDebugInspectorIntegration::cleanup()
@@ -125,14 +127,24 @@ void tst_QQmlEngineDebugInspectorIntegration::cleanup()
delete m_inspectorClient;
}
+void tst_QQmlEngineDebugInspectorIntegration::connect_data()
+{
+ QTest::addColumn<bool>("restrictMode");
+ QTest::newRow("unrestricted") << false;
+ QTest::newRow("restricted") << true;
+}
+
void tst_QQmlEngineDebugInspectorIntegration::connect()
{
+ QFETCH(bool, restrictMode);
+ init(restrictMode);
QTRY_COMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
QTRY_COMPARE(m_engineDebugClient->state(), QQmlDebugClient::Enabled);
}
void tst_QQmlEngineDebugInspectorIntegration::clearObjectReferenceHashonReloadQml()
{
+ init(true);
QTRY_COMPARE(m_engineDebugClient->state(), QQmlDebugClient::Enabled);
bool success = false;
QmlDebugObjectReference rootObject = findRootObject();
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index d3bb5c38ca..bc3220ad8c 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,
@@ -349,9 +351,8 @@ void tst_QQmlEngineDebugService::initTestCase()
bool ok = m_conn->waitForConnected();
QVERIFY(ok);
- QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
m_dbg = new QQmlEngineDebugClient(m_conn);
- QTRY_VERIFY(m_dbg->state() == QQmlEngineDebugClient::Enabled);
+ QTRY_COMPARE(m_dbg->state(), QQmlEngineDebugClient::Enabled);
}
void tst_QQmlEngineDebugService::cleanupTestCase()
@@ -372,7 +373,7 @@ void tst_QQmlEngineDebugService::setMethodBody()
QVariant rv;
QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, rv)));
- QVERIFY(rv == QVariant(qreal(3)));
+ QCOMPARE(rv, QVariant(qreal(3)));
QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethodNoArgs", "return 7",
@@ -382,7 +383,7 @@ void tst_QQmlEngineDebugService::setMethodBody()
QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, rv)));
- QVERIFY(rv == QVariant(qreal(7)));
+ QCOMPARE(rv, QVariant(qreal(7)));
}
// With args
@@ -390,7 +391,7 @@ void tst_QQmlEngineDebugService::setMethodBody()
QVariant rv;
QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
- QVERIFY(rv == QVariant(qreal(28)));
+ QCOMPARE(rv, QVariant(qreal(28)));
QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethod", "return a + 7",
&success));
@@ -399,7 +400,7 @@ void tst_QQmlEngineDebugService::setMethodBody()
QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
- QVERIFY(rv == QVariant(qreal(26)));
+ QCOMPARE(rv, QVariant(qreal(26)));
}
}
@@ -731,7 +732,7 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
QVERIFY(success);
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
- QVERIFY(m_dbg->objects().count() == 1);
+ QCOMPARE(m_dbg->objects().count(), 1);
QmlDebugObjectReference obj = m_dbg->objects().first();
// check source as defined in main()
@@ -1018,7 +1019,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()
@@ -1224,7 +1225,7 @@ int main(int argc, char *argv[])
char **_argv = new char*[_argc];
for (int i = 0; i < argc; ++i)
_argv[i] = argv[i];
- char arg[] = "-qmljsdebugger=port:3768";
+ char arg[] = "-qmljsdebugger=port:3768,services:QmlDebugger";
_argv[_argc - 1] = arg;
QGuiApplication app(_argc, _argv);
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
index 5ed866c04d..70833f5e2c 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
@@ -60,7 +60,7 @@ public:
}
private:
- void startQmlsceneProcess(const char *qmlFile);
+ void startQmlsceneProcess(const char *qmlFile, bool restrictMode = true);
private:
QQmlDebugProcess *m_process;
@@ -68,18 +68,20 @@ private:
QQmlInspectorClient *m_client;
private slots:
- void init();
void cleanup();
+ void connect_data();
void connect();
void showAppOnTop();
void reloadQml();
void reloadQmlWindow();
};
-void tst_QQmlInspector::startQmlsceneProcess(const char * /* qmlFile */)
+void tst_QQmlInspector::startQmlsceneProcess(const char * /* qmlFile */, bool restrictServices)
{
- const QString argument = "-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block";
+ const QString argument = QString::fromLatin1("-qmljsdebugger=port:%1,%2,block%3")
+ .arg(STR_PORT_FROM).arg(STR_PORT_TO)
+ .arg(restrictServices ? QStringLiteral(",services:QmlInspector") : QString());
// ### This should be using qml instead of qmlscene, but can't because of QTBUG-33376 (same as the XFAIL testcase)
m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this);
@@ -87,15 +89,13 @@ void tst_QQmlInspector::startQmlsceneProcess(const char * /* qmlFile */)
QVERIFY2(m_process->waitForSessionStart(),
"Could not launch application, or did not get 'Waiting for connection'.");
- QQmlDebugConnection *m_connection = new QQmlDebugConnection();
+ m_connection = new QQmlDebugConnection();
m_client = new QQmlInspectorClient(m_connection);
- const int port = m_process->debugPort();
- m_connection->connectToHost(QLatin1String("127.0.0.1"), port);
-}
+ m_connection->connectToHost(QLatin1String("127.0.0.1"), m_process->debugPort());
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
-void tst_QQmlInspector::init()
-{
}
void tst_QQmlInspector::cleanup()
@@ -104,20 +104,31 @@ void tst_QQmlInspector::cleanup()
qDebug() << "Process State:" << m_process->state();
qDebug() << "Application Output:" << m_process->output();
}
- delete m_process;
- delete m_connection;
delete m_client;
+ m_client = 0;
+ delete m_connection;
+ m_connection = 0;
+ delete m_process;
+ m_process = 0;
+}
+
+void tst_QQmlInspector::connect_data()
+{
+ QTest::addColumn<bool>("restrictMode");
+ QTest::newRow("unrestricted") << false;
+ QTest::newRow("restricted") << true;
}
void tst_QQmlInspector::connect()
{
- startQmlsceneProcess("qtquick2.qml");
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+ QFETCH(bool, restrictMode);
+ startQmlsceneProcess("qtquick2.qml", restrictMode);
}
void tst_QQmlInspector::showAppOnTop()
{
startQmlsceneProcess("qtquick2.qml");
+ QVERIFY(m_client);
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setShowAppOnTop(true);
@@ -132,6 +143,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 +169,7 @@ void tst_QQmlInspector::reloadQml()
void tst_QQmlInspector::reloadQmlWindow()
{
startQmlsceneProcess("window.qml");
+ QVERIFY(m_client);
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
QByteArray fileContents;
@@ -173,8 +186,8 @@ void tst_QQmlInspector::reloadQmlWindow()
QVERIFY(QQmlDebugTest::waitForSignal(m_client, SIGNAL(responseReceived())));
QEXPECT_FAIL("", "cannot debug with a QML file containing a top-level Window", Abort); // QTBUG-33376
- QTRY_COMPARE(m_process->output().contains(
- QString("version 2.0")), true);
+ // TODO: remove the timeout once we don't expect it to fail anymore.
+ QTRY_VERIFY_WITH_TIMEOUT(m_process->output().contains(QString("version 2.0")), 1);
QCOMPARE(m_client->m_requestResult, true);
QCOMPARE(m_client->m_reloadRequestId, m_client->m_responseId);
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
new file mode 100644
index 0000000000..18b8947172
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 100
+ height: 62
+
+ Timer {
+ running: true
+ repeat: true
+ interval: 50
+ onTriggered: height = (2 * height) % 99;
+ }
+}
+
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
index ec84139797..e422d3ef99 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
@@ -21,4 +21,5 @@ OTHER_FILES += \
data/scenegraphTest.qml \
data/TestImage_2x2.png \
data/signalSourceLocation.qml \
- data/javascript.qml
+ data/javascript.qml \
+ data/timer.qml
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 094bf43549..0e63e18952 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -139,16 +139,18 @@ public:
{
}
- QList<QQmlProfilerData> qmlMessages;
- QList<QQmlProfilerData> javascriptMessages;
- QList<QQmlProfilerData> jsHeapMessages;
- QList<QQmlProfilerData> asynchronousMessages;
- QList<QQmlProfilerData> pixmapMessages;
+ QVector<QQmlProfilerData> qmlMessages;
+ QVector<QQmlProfilerData> javascriptMessages;
+ QVector<QQmlProfilerData> jsHeapMessages;
+ QVector<QQmlProfilerData> asynchronousMessages;
+ QVector<QQmlProfilerData> pixmapMessages;
- void setTraceState(bool enabled) {
+ void setTraceState(bool enabled, quint32 flushInterval = 0) {
QByteArray message;
QDataStream stream(&message, QIODevice::WriteOnly);
stream << enabled;
+ if (enabled && flushInterval)
+ stream << -1 << std::numeric_limits<quint64>::max() << flushInterval;
sendMessage(message);
}
@@ -195,7 +197,7 @@ private:
CheckAll = CheckMessageType | CheckDetailType | CheckLine | CheckColumn | CheckDataEndsWith
};
- void connect(bool block, const QString &testFile);
+ void connect(bool block, const QString &testFile, bool restrictServices = true);
void checkTraceReceived();
void checkJsHeap();
bool verify(MessageListType type, int expectedPosition, const QQmlProfilerData &expected,
@@ -204,15 +206,15 @@ private:
private slots:
void cleanup();
- void blockingConnectWithTraceEnabled();
- void blockingConnectWithTraceDisabled();
- void nonBlockingConnect();
+ void connect_data();
+ void connect();
void pixmapCacheData();
void scenegraphData();
void profileOnExit();
void controlFromJS();
void signalSourceLocation();
void javascript();
+ void flushInterval();
};
#define VERIFY(type, position, expected, checks) QVERIFY(verify(type, position, expected, checks))
@@ -354,17 +356,16 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message)
qmlMessages.append(data);
}
-void tst_QQmlProfilerService::connect(bool block, const QString &testFile)
+void tst_QQmlProfilerService::connect(bool block, const QString &testFile, bool restrictServices)
{
// ### Still using qmlscene due to QTBUG-33377
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
QStringList arguments;
- if (block)
- arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block");
- else
- arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO );
-
- arguments << QQmlDataTest::instance()->testFile(testFile);
+ arguments << QString::fromLatin1("-qmljsdebugger=port:%1,%2%3%4")
+ .arg(STR_PORT_FROM).arg(STR_PORT_TO)
+ .arg(block ? QStringLiteral(",block") : QString())
+ .arg(restrictServices ? QStringLiteral(",services:CanvasFrameRate") : QString())
+ << QQmlDataTest::instance()->testFile(testFile);
m_process = new QQmlDebugProcess(executable, this);
m_process->start(QStringList() << arguments);
@@ -375,6 +376,8 @@ void tst_QQmlProfilerService::connect(bool block, const QString &testFile)
const int port = m_process->debugPort();
m_connection->connectToHost(QLatin1String("127.0.0.1"), port);
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
}
void tst_QQmlProfilerService::checkTraceReceived()
@@ -449,7 +452,7 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
int expectedPosition, const QQmlProfilerData &expected,
quint32 checks)
{
- QList<QQmlProfilerData> *target = 0;
+ QVector<QQmlProfilerData> *target = 0;
switch (type) {
case MessageListQML: target = &(m_client->qmlMessages); break;
case MessageListJavaScript: target = &(m_client->javascriptMessages); break;
@@ -509,7 +512,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 +550,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;
@@ -557,37 +560,32 @@ void tst_QQmlProfilerService::cleanup()
m_connection = 0;
}
-void tst_QQmlProfilerService::blockingConnectWithTraceEnabled()
+void tst_QQmlProfilerService::connect_data()
{
- connect(true, "test.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
-
- m_client->setTraceState(true);
- m_client->setTraceState(false);
- checkTraceReceived();
- checkJsHeap();
+ QTest::addColumn<bool>("blockMode");
+ QTest::addColumn<bool>("restrictMode");
+ QTest::addColumn<bool>("traceEnabled");
+ QTest::newRow("normal/unrestricted/disabled") << false << false << false;
+ QTest::newRow("block/unrestricted/disabled") << true << false << false;
+ QTest::newRow("normal/restricted/disabled") << false << true << false;
+ QTest::newRow("block/restricted/disabled") << true << true << false;
+ QTest::newRow("normal/unrestricted/enabled") << false << false << true;
+ QTest::newRow("block/unrestricted/enabled") << true << false << true;
+ QTest::newRow("normal/restricted/enabled") << false << true << true;
+ QTest::newRow("block/restricted/enabled") << true << true << true;
}
-void tst_QQmlProfilerService::blockingConnectWithTraceDisabled()
+void tst_QQmlProfilerService::connect()
{
- connect(true, "test.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+ QFETCH(bool, blockMode);
+ QFETCH(bool, restrictMode);
+ QFETCH(bool, traceEnabled);
- m_client->setTraceState(false);
- m_client->setTraceState(true);
- m_client->setTraceState(false);
- checkTraceReceived();
- checkJsHeap();
-}
-
-void tst_QQmlProfilerService::nonBlockingConnect()
-{
- connect(false, "test.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+ connect(blockMode, "test.qml", restrictMode);
+ // if the engine is waiting, then the first message determines if it starts with trace enabled
+ if (!traceEnabled)
+ m_client->setTraceState(false);
m_client->setTraceState(true);
m_client->setTraceState(false);
checkTraceReceived();
@@ -597,8 +595,6 @@ void tst_QQmlProfilerService::nonBlockingConnect()
void tst_QQmlProfilerService::pixmapCacheData()
{
connect(true, "pixmapCacheTest.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(true);
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
@@ -636,8 +632,6 @@ void tst_QQmlProfilerService::pixmapCacheData()
void tst_QQmlProfilerService::scenegraphData()
{
connect(true, "scenegraphTest.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(true);
@@ -690,8 +684,6 @@ void tst_QQmlProfilerService::scenegraphData()
void tst_QQmlProfilerService::profileOnExit()
{
connect(true, "exit.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(true);
@@ -702,8 +694,6 @@ void tst_QQmlProfilerService::profileOnExit()
void tst_QQmlProfilerService::controlFromJS()
{
connect(true, "controlFromJS.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(false);
checkTraceReceived();
@@ -713,8 +703,6 @@ void tst_QQmlProfilerService::controlFromJS()
void tst_QQmlProfilerService::signalSourceLocation()
{
connect(true, "signalSourceLocation.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(true);
while (!(m_process->output().contains(QLatin1String("500"))))
@@ -738,8 +726,6 @@ void tst_QQmlProfilerService::signalSourceLocation()
void tst_QQmlProfilerService::javascript()
{
connect(true, "javascript.qml");
- QVERIFY(m_client);
- QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(true);
while (!(m_process->output().contains(QLatin1String("done"))))
@@ -766,6 +752,22 @@ void tst_QQmlProfilerService::javascript()
VERIFY(MessageListJavaScript, 21, expected, CheckMessageType | CheckDetailType);
}
+void tst_QQmlProfilerService::flushInterval()
+{
+ connect(true, "timer.qml");
+
+ m_client->setTraceState(true, 1);
+
+ // Make sure we get multiple messages
+ QTRY_VERIFY(m_client->qmlMessages.length() > 0);
+ QVERIFY(m_client->qmlMessages.length() < 100);
+ QTRY_VERIFY(m_client->qmlMessages.length() > 100);
+
+ m_client->setTraceState(false);
+ checkTraceReceived();
+ checkJsHeap();
+}
+
QTEST_MAIN(tst_QQmlProfilerService)
#include "tst_qqmlprofilerservice.moc"
diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp
index 74f22e6997..51d706b818 100644
--- a/tests/auto/qml/debugger/shared/debugutil.cpp
+++ b/tests/auto/qml/debugger/shared/debugutil.cpp
@@ -91,7 +91,7 @@ QQmlDebugProcess::QQmlDebugProcess(const QString &executable, QObject *parent)
m_timer.setSingleShot(true);
m_timer.setInterval(5000);
connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processAppOutput()));
- connect(&m_process, SIGNAL(error(QProcess::ProcessError)),
+ connect(&m_process, SIGNAL(errorOccurred(QProcess::ProcessError)),
this, SLOT(processError(QProcess::ProcessError)));
connect(&m_timer, SIGNAL(timeout()), SLOT(timeout()));
}
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/debugger/shared/qqmldebugtestservice.cpp b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
index 990cb1caa1..e62aa2ce61 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
@@ -37,13 +37,12 @@
QQmlDebugTestService::QQmlDebugTestService(const QString &s, float version, QObject *parent)
: QQmlDebugService(s, version, parent)
{
- registerService();
}
void QQmlDebugTestService::messageReceived(const QByteArray &ba)
{
Q_ASSERT(QThread::currentThread() != thread());
- QMetaObject::invokeMethod(this, "_sendMessage", Qt::QueuedConnection, Q_ARG(QByteArray, ba));
+ emit messageToClient(name(), ba);
}
void QQmlDebugTestService::stateAboutToBeChanged(QQmlDebugService::State)
@@ -56,8 +55,3 @@ void QQmlDebugTestService::stateChanged(State)
Q_ASSERT(QThread::currentThread() != thread());
emit stateHasChanged();
}
-
-void QQmlDebugTestService::_sendMessage(const QByteArray &msg)
-{
- QQmlDebugService::sendMessage(msg);
-}
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
index 7cb09798de..cc24f3c119 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
@@ -46,9 +46,6 @@ public:
signals:
void stateHasChanged();
-private slots:
- void _sendMessage(const QByteArray &msg);
-
protected:
virtual void messageReceived(const QByteArray &ba);
virtual void stateAboutToBeChanged(State state);
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 5a9d6d20eb..4c7dba9f90 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -336,7 +336,7 @@ void tst_QJSEngine::constructWithParent()
QJSEngine *engine = new QJSEngine(&obj);
ptr = engine;
}
- QVERIFY(ptr == 0);
+ QVERIFY(ptr.isNull());
}
void tst_QJSEngine::newObject()
@@ -631,7 +631,7 @@ void tst_QJSEngine::newQObject_ownership()
eng.collectGarbage();
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
- QVERIFY(ptr == 0);
+ QVERIFY(ptr.isNull());
}
{
QPointer<QObject> ptr = new QObject(this);
@@ -641,7 +641,7 @@ void tst_QJSEngine::newQObject_ownership()
}
QObject *before = ptr;
eng.collectGarbage();
- QVERIFY(ptr == before);
+ QCOMPARE(ptr.data(), before);
delete ptr;
}
{
@@ -662,7 +662,7 @@ void tst_QJSEngine::newQObject_ownership()
// no parent, so it should be like ScriptOwnership
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
- QVERIFY(ptr == 0);
+ QVERIFY(ptr.isNull());
}
{
QObject *parent = new QObject();
@@ -1258,7 +1258,7 @@ void tst_QJSEngine::valueConversion_QVariant()
{
QVariant tmp1;
QVariant tmp2(QMetaType::QVariant, &tmp1);
- QVERIFY(QMetaType::Type(tmp2.type()) == QMetaType::QVariant);
+ QCOMPARE(QMetaType::Type(tmp2.type()), QMetaType::QVariant);
QJSValue val1 = eng.toScriptValue(tmp1);
QJSValue val2 = eng.toScriptValue(tmp2);
@@ -1273,9 +1273,9 @@ void tst_QJSEngine::valueConversion_QVariant()
QVariant tmp1(123);
QVariant tmp2(QMetaType::QVariant, &tmp1);
QVariant tmp3(QMetaType::QVariant, &tmp2);
- QVERIFY(QMetaType::Type(tmp1.type()) == QMetaType::Int);
- QVERIFY(QMetaType::Type(tmp2.type()) == QMetaType::QVariant);
- QVERIFY(QMetaType::Type(tmp3.type()) == QMetaType::QVariant);
+ QCOMPARE(QMetaType::Type(tmp1.type()), QMetaType::Int);
+ QCOMPARE(QMetaType::Type(tmp2.type()), QMetaType::QVariant);
+ QCOMPARE(QMetaType::Type(tmp3.type()), QMetaType::QVariant);
QJSValue val1 = eng.toScriptValue(tmp2);
QJSValue val2 = eng.toScriptValue(tmp3);
@@ -1285,8 +1285,8 @@ void tst_QJSEngine::valueConversion_QVariant()
QVERIFY(val1.isVariant());
QEXPECT_FAIL("", "Variant are unrwapped, maybe we should not...", Continue);
QVERIFY(val2.isVariant());
- QVERIFY(val1.toVariant().toInt() == 123);
- QVERIFY(eng.toScriptValue(val2.toVariant()).toVariant().toInt() == 123);
+ QCOMPARE(val1.toVariant().toInt(), 123);
+ QCOMPARE(eng.toScriptValue(val2.toVariant()).toVariant().toInt(), 123);
}
{
QJSValue val = eng.toScriptValue(QVariant(true));
@@ -1472,7 +1472,7 @@ void tst_QJSEngine::collectGarbage()
eng.collectGarbage();
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
- QVERIFY(ptr == 0);
+ QVERIFY(ptr.isNull());
}
void tst_QJSEngine::gcWithNestedDataStructure()
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index d608379d52..bea44cb6e3 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -1076,7 +1076,7 @@ void tst_QJSValue::toVariant()
QVariantList listOut = ret.toList();
QCOMPARE(listOut.size(), listIn.size());
for (int i = 0; i < listIn.size(); ++i)
- QVERIFY(listOut.at(i) == listIn.at(i));
+ QCOMPARE(listOut.at(i), listIn.at(i));
// round-trip conversion
QJSValue array2 = eng.toScriptValue(ret);
QVERIFY(array2.isArray());
@@ -2261,7 +2261,7 @@ void tst_QJSValue::castToPointer()
QCOMPARE(*cp, c);
QBrush *bp = qjsvalue_cast<QBrush*>(v);
- QVERIFY(bp == 0);
+ QVERIFY(!bp);
QJSValue v2 = eng.toScriptValue(qVariantFromValue(cp));
QCOMPARE(qjsvalue_cast<QColor*>(v2), cp);
@@ -2465,15 +2465,15 @@ void tst_QJSValue::engineDeleted()
delete eng;
QVERIFY(v1.isUndefined());
- QVERIFY(v1.engine() == 0);
+ QVERIFY(!v1.engine());
QVERIFY(v2.isUndefined());
- QVERIFY(v2.engine() == 0);
+ QVERIFY(!v2.engine());
QVERIFY(v3.isUndefined());
- QVERIFY(v3.engine() == 0);
+ QVERIFY(!v3.engine());
QVERIFY(v4.isUndefined());
- QVERIFY(v4.engine() == 0);
+ QVERIFY(!v4.engine());
QVERIFY(v5.isString()); // was not bound to engine
- QVERIFY(v5.engine() == 0);
+ QVERIFY(!v5.engine());
QVERIFY(v3.property("foo").isUndefined());
}
diff --git a/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
index 6049e423e8..81a79331c3 100644
--- a/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
+++ b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
@@ -92,7 +92,7 @@ void tst_QJSValueIterator::iterateForward()
QFETCH(QStringList, propertyNames);
QFETCH(QStringList, propertyValues);
QMap<QString, QString> pmap;
- QVERIFY(propertyNames.size() == propertyValues.size());
+ QCOMPARE(propertyNames.size(), propertyValues.size());
QJSEngine engine;
QJSValue object = engine.newObject();
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 430a90b800..b61eca730f 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -37,6 +37,7 @@ PRIVATETESTS += \
qqmldirparser \
qqmlglobal \
qqmllanguage \
+ qqmlopenmetaobject \
qqmlproperty \
qqmlpropertycache \
qqmlpropertymap \
@@ -60,7 +61,8 @@ PRIVATETESTS += \
qqmlenginecleanup \
v4misc \
qqmltranslation \
- qqmlimport
+ qqmlimport \
+ qqmlobjectmodel
qtHaveModule(widgets) {
PUBLICTESTS += \
@@ -70,7 +72,7 @@ qtHaveModule(widgets) {
SUBDIRS += $$PUBLICTESTS
SUBDIRS += $$METATYPETESTS
-!winrt: SUBDIRS += debugger # no QProcess on winrt
+!winrt:!contains(QT_CONFIG, no-qml-debug): SUBDIRS += debugger # no QProcess on winrt
contains(QT_CONFIG, private_tests) {
SUBDIRS += $$PRIVATETESTS
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index bb159d5931..85579a6019 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();
@@ -157,7 +158,7 @@ void tst_qqmlcomponent::qmlIncubateObject()
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), false);
- QTRY_VERIFY(object->property("test2").toBool() == true);
+ QTRY_VERIFY(object->property("test2").toBool());
delete object;
}
@@ -250,7 +251,7 @@ void tst_qqmlcomponent::qmlCreateObjectWithProperties()
QObject *testObject1 = object->property("declarativerectangle").value<QObject*>();
QVERIFY(testObject1);
- QVERIFY(testObject1->parent() == object);
+ QCOMPARE(testObject1->parent(), object);
QCOMPARE(testObject1->property("x").value<int>(), 17);
QCOMPARE(testObject1->property("y").value<int>(), 17);
QCOMPARE(testObject1->property("color").value<QColor>(), QColor(255,255,255));
@@ -260,7 +261,7 @@ void tst_qqmlcomponent::qmlCreateObjectWithProperties()
QObject *testObject2 = object->property("declarativeitem").value<QObject*>();
QVERIFY(testObject2);
- QVERIFY(testObject2->parent() == object);
+ QCOMPARE(testObject2->parent(), object);
//QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2");
QCOMPARE(testObject2->property("x").value<int>(), 17);
QCOMPARE(testObject2->property("y").value<int>(), 17);
@@ -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
@@ -418,7 +448,7 @@ void tst_qqmlcomponent::componentUrlCanonicalization()
QQmlComponent component(&engine, testFileUrl("componentUrlCanonicalization.5.qml"));
QTest::ignoreMessage(QtWarningMsg, QLatin1String("QQmlComponent: Component is not ready").data());
QScopedPointer<QObject> object(component.create());
- QVERIFY(object == 0);
+ QVERIFY(object.isNull());
}
}
diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
index 45393bf2f0..e529c74acc 100644
--- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
+++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
@@ -72,7 +72,7 @@ void tst_qqmlconnections::defaultValues()
QQmlConnections *item = qobject_cast<QQmlConnections*>(c.create());
QVERIFY(item != 0);
- QVERIFY(item->target() == 0);
+ QVERIFY(!item->target());
delete item;
}
@@ -86,7 +86,7 @@ void tst_qqmlconnections::properties()
QVERIFY(item != 0);
QVERIFY(item != 0);
- QVERIFY(item->target() == item);
+ QCOMPARE(item->target(), item);
delete item;
}
@@ -146,7 +146,7 @@ void tst_qqmlconnections::targetChanged()
QQuickItem *item2 = item->findChild<QQuickItem*>("item2");
QVERIFY(item2);
- QVERIFY(connections->target() == item2);
+ QCOMPARE(connections->target(), item2);
// If we don't crash then we're OK
@@ -211,9 +211,9 @@ void tst_qqmlconnections::errors()
QQmlEngine engine;
QQmlComponent c(&engine, url);
- QVERIFY(c.isError() == true);
+ QVERIFY(c.isError());
QList<QQmlError> errors = c.errors();
- QVERIFY(errors.count() == 1);
+ QCOMPARE(errors.count(), 1);
QCOMPARE(errors.at(0).description(), error);
}
diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
index 1ee675a91d..98e3a53b81 100644
--- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
+++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
@@ -47,7 +47,7 @@ private slots:
void logging();
void tracing();
void profiling();
- void assert();
+ void testAssert();
void exception();
private:
@@ -122,7 +122,7 @@ void tst_qqmlconsole::profiling()
delete object;
}
-void tst_qqmlconsole::assert()
+void tst_qqmlconsole::testAssert()
{
QUrl testUrl = testFileUrl("assert.qml");
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 1bd070c2d0..18ef7ac31d 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -433,12 +433,12 @@ void tst_qqmlcontext::idAsContextProperty()
QVERIFY(obj);
QVariant a = obj->property("a");
- QVERIFY(a.userType() == QMetaType::QObjectStar);
+ QCOMPARE(a.userType(), int(QMetaType::QObjectStar));
QVariant ctxt = qmlContext(obj)->contextProperty("myObject");
- QVERIFY(ctxt.userType() == QMetaType::QObjectStar);
+ QCOMPARE(ctxt.userType(), int(QMetaType::QObjectStar));
- QVERIFY(a == ctxt);
+ QCOMPARE(a, ctxt);
delete obj;
}
@@ -455,20 +455,20 @@ void tst_qqmlcontext::readOnlyContexts()
QQmlContext *context = qmlContext(obj);
QVERIFY(context);
- QVERIFY(qvariant_cast<QObject*>(context->contextProperty("me")) == obj);
- QVERIFY(context->contextObject() == obj);
+ QCOMPARE(qvariant_cast<QObject*>(context->contextProperty("me")), obj);
+ QCOMPARE(context->contextObject(), obj);
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set property on internal context.");
context->setContextProperty("hello", 12);
- QVERIFY(context->contextProperty("hello") == QVariant());
+ QCOMPARE(context->contextProperty("hello"), QVariant());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set property on internal context.");
context->setContextProperty("hello", obj);
- QVERIFY(context->contextProperty("hello") == QVariant());
+ QCOMPARE(context->contextProperty("hello"), QVariant());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set context object for internal context.");
context->setContextObject(0);
- QVERIFY(context->contextObject() == obj);
+ QCOMPARE(context->contextObject(), obj);
delete obj;
}
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/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index eb25eb70f4..222e594d1a 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -521,7 +521,7 @@ void tst_qqmlecmascript::idShortcutInvalidates()
QVERIFY(object != 0);
QVERIFY(object->objectProperty() != 0);
delete object->objectProperty();
- QVERIFY(object->objectProperty() == 0);
+ QVERIFY(!object->objectProperty());
delete object;
}
@@ -531,7 +531,7 @@ void tst_qqmlecmascript::idShortcutInvalidates()
QVERIFY(object != 0);
QVERIFY(object->objectProperty() != 0);
delete object->objectProperty();
- QVERIFY(object->objectProperty() == 0);
+ QVERIFY(!object->objectProperty());
delete object;
}
}
@@ -885,7 +885,7 @@ void tst_qqmlecmascript::deferredProperties()
qobject_cast<MyDeferredObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->value(), 0);
- QVERIFY(object->objectProperty() == 0);
+ QVERIFY(!object->objectProperty());
QVERIFY(object->objectProperty2() != 0);
qmlExecuteDeferred(object);
QCOMPARE(object->value(), 10);
@@ -908,8 +908,8 @@ void tst_qqmlecmascript::deferredPropertiesErrors()
qobject_cast<MyDeferredObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->value(), 0);
- QVERIFY(object->objectProperty() == 0);
- QVERIFY(object->objectProperty2() == 0);
+ QVERIFY(!object->objectProperty());
+ QVERIFY(!object->objectProperty2());
QString warning = component.url().toString() + ":6:21: Unable to assign [undefined] to QObject*";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
@@ -932,7 +932,7 @@ void tst_qqmlecmascript::deferredPropertiesInComponents()
MyDeferredObject *defObjectA =
qobject_cast<MyDeferredObject *>(object->property("deferredInside").value<QObject*>());
QVERIFY(defObjectA != 0);
- QVERIFY(defObjectA->objectProperty() == 0);
+ QVERIFY(!defObjectA->objectProperty());
qmlExecuteDeferred(defObjectA);
QVERIFY(defObjectA->objectProperty() != 0);
@@ -941,7 +941,7 @@ void tst_qqmlecmascript::deferredPropertiesInComponents()
MyDeferredObject *defObjectB =
qobject_cast<MyDeferredObject *>(object->property("deferredOutside").value<QObject*>());
QVERIFY(defObjectB != 0);
- QVERIFY(defObjectB->objectProperty() == 0);
+ QVERIFY(!defObjectB->objectProperty());
qmlExecuteDeferred(defObjectB);
QVERIFY(defObjectB->objectProperty() != 0);
@@ -995,7 +995,7 @@ void tst_qqmlecmascript::overrideExtensionProperties()
qobject_cast<OverrideDefaultPropertyObject *>(component.create());
QVERIFY(object != 0);
QVERIFY(object->secondProperty() != 0);
- QVERIFY(object->firstProperty() == 0);
+ QVERIFY(!object->firstProperty());
delete object;
}
@@ -1459,7 +1459,7 @@ void tst_qqmlecmascript::aliasPropertyReset()
QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() != 0);
QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
QMetaObject::invokeMethod(object, "resetAliased");
- QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
+ QVERIFY(!object->property("sourceComponentAlias").value<QQmlComponent*>());
QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
delete object;
@@ -1470,7 +1470,7 @@ void tst_qqmlecmascript::aliasPropertyReset()
QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() != 0);
QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
QMetaObject::invokeMethod(object, "resetAlias");
- QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
+ QVERIFY(!object->property("sourceComponentAlias").value<QQmlComponent*>());
QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
delete object;
@@ -1482,7 +1482,7 @@ void tst_qqmlecmascript::aliasPropertyReset()
QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
QMetaObject::invokeMethod(object, "resetAlias");
- QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
+ QVERIFY(!object->property("sourceComponentAlias").value<QQmlComponent*>());
QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
delete object;
@@ -1498,9 +1498,9 @@ void tst_qqmlecmascript::aliasPropertyReset()
delete loader;
QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0); // deletion should have caused value unset.
QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
- QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
+ QVERIFY(!object->property("sourceComponentAlias").value<QQmlComponent*>());
QMetaObject::invokeMethod(object, "setAlias"); // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
- QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
+ QVERIFY(!object->property("sourceComponentAlias").value<QQmlComponent*>());
delete object;
// test that binding an alias property to an undefined value works correctly
@@ -1680,7 +1680,7 @@ void tst_qqmlecmascript::dynamicDestruction()
QObject *o = component.create();
QVERIFY(o != 0);
- QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
+ QVERIFY(!qvariant_cast<QObject*>(o->property("objectProperty")));
QMetaObject::invokeMethod(o, "create");
@@ -1691,7 +1691,7 @@ void tst_qqmlecmascript::dynamicDestruction()
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
- QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
+ QVERIFY(!qvariant_cast<QObject*>(o->property("objectProperty")));
delete o;
}
@@ -1702,19 +1702,19 @@ void tst_qqmlecmascript::dynamicDestruction()
QQmlComponent component(&engine, testFileUrl("dynamicDeletion.3.qml"));
QObject *o = component.create();
QVERIFY(o != 0);
- QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
+ QVERIFY(!qvariant_cast<QObject*>(o->property("objectProperty")));
QMetaObject::invokeMethod(o, "create");
createdQmlObject = qvariant_cast<QObject*>(o->property("objectProperty"));
QVERIFY(createdQmlObject);
QMetaObject::invokeMethod(o, "destroy");
- QVERIFY(qvariant_cast<bool>(o->property("test")) == false);
+ QCOMPARE(qvariant_cast<bool>(o->property("test")), false);
for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
QTest::qWait(100);
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
}
- QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
- QVERIFY(qvariant_cast<bool>(o->property("test")) == true);
+ QVERIFY(!qvariant_cast<QObject*>(o->property("objectProperty")));
+ QCOMPARE(qvariant_cast<bool>(o->property("test")), true);
delete o;
}
}
@@ -1750,9 +1750,9 @@ void tst_qqmlecmascript::objectHasOwnProperty()
// test QObjects in QML
QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
- QVERIFY(object->property("result").value<bool>() == true);
+ QVERIFY(object->property("result").value<bool>());
QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
- QVERIFY(object->property("result").value<bool>() == false);
+ QVERIFY(!object->property("result").value<bool>());
// now test other types in QML
QObject *child = object->findChild<QObject*>("typeObj");
@@ -1846,7 +1846,7 @@ void tst_qqmlecmascript::uncreatableExtendedObjectFailureCheck()
QQmlComponent component(&engine, testFileUrl("uncreatableExtendedObjectFailureCheck.qml"));
QObject *object = component.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
}
/*
@@ -2235,7 +2235,7 @@ void tst_qqmlecmascript::dynamicCreationCrash()
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
QMetaObject::invokeMethod(object, "dontCrash");
QObject *created = object->objectProperty();
- QVERIFY(created == 0);
+ QVERIFY(!created);
delete object;
}
@@ -2993,7 +2993,7 @@ void tst_qqmlecmascript::listToVariant()
QVariant v = object->property("test");
QCOMPARE(v.userType(), qMetaTypeId<QQmlListReference>());
- QVERIFY(qvariant_cast<QQmlListReference>(v).object() == &container);
+ QCOMPARE(qvariant_cast<QQmlListReference>(v).object(), &container);
delete object;
}
@@ -3260,7 +3260,7 @@ void tst_qqmlecmascript::ownership()
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
- QVERIFY(own.object == 0);
+ QVERIFY(own.object.isNull());
delete object;
}
@@ -3319,7 +3319,7 @@ void tst_qqmlecmascript::cppOwnershipReturnValue()
QQmlEngine engine;
engine.rootContext()->setContextProperty("source", &source);
- QVERIFY(source.value == 0);
+ QVERIFY(source.value.isNull());
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
@@ -3347,7 +3347,7 @@ void tst_qqmlecmascript::ownershipCustomReturnValue()
QQmlEngine engine;
engine.rootContext()->setContextProperty("source", &source);
- QVERIFY(source.value == 0);
+ QVERIFY(source.value.isNull());
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
@@ -3364,7 +3364,7 @@ void tst_qqmlecmascript::ownershipCustomReturnValue()
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
- QVERIFY(source.value == 0);
+ QVERIFY(source.value.isNull());
}
//the return value from getObject will be JS ownership,
@@ -3446,7 +3446,7 @@ void tst_qqmlecmascript::ownershipQmlIncubated()
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
- QVERIFY(object->property("incubatedItem").value<QObject*>() == 0);
+ QVERIFY(!object->property("incubatedItem").value<QObject*>());
delete object;
}
@@ -3863,7 +3863,7 @@ void tst_qqmlecmascript::singletonType()
QObject *object = component.create();
if (!errorMessage.isEmpty()) {
- QVERIFY(object == 0);
+ QVERIFY(!object);
} else {
QVERIFY(object != 0);
for (int i = 0; i < readProperties.size(); ++i)
@@ -3920,7 +3920,7 @@ void tst_qqmlecmascript::singletonTypeImportOrder()
QQmlComponent component(&engine, testFileUrl("singletontype/singletonTypeImportOrder.qml"));
QObject *object = component.create();
QVERIFY(object);
- QVERIFY(object->property("v") == 1);
+ QCOMPARE(object->property("v").toInt(), 1);
delete object;
}
@@ -3929,7 +3929,7 @@ void tst_qqmlecmascript::singletonTypeResolution()
QQmlComponent component(&engine, testFileUrl("singletontype/singletonTypeResolution.qml"));
QObject *object = component.create();
QVERIFY(object);
- QVERIFY(object->property("success") == true);
+ QVERIFY(object->property("success").toBool());
delete object;
}
@@ -3941,12 +3941,12 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
QV4::ScopedArrayObject scripts(scope, ctxt->importedScripts.value());
- QV4::ScopedValue qml(scope);
+ QV4::Scoped<QV4::QmlContextWrapper> qml(scope);
for (quint32 i = 0; i < scripts->getLength(); ++i) {
QQmlContextData *scriptContext, *newContext;
qml = scripts->getIndexed(i);
- scriptContext = QV4::QmlContextWrapper::getContext(qml);
+ scriptContext = qml ? qml->getContext() : 0;
qml = QV4::Encode::undefined();
{
@@ -3957,8 +3957,8 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
ctxt->engine->collectGarbage();
qml = scripts->getIndexed(i);
- newContext = QV4::QmlContextWrapper::getContext(qml);
- QVERIFY(scriptContext == newContext);
+ newContext = qml ? qml->getContext() : 0;
+ QCOMPARE(scriptContext, newContext);
}
}
@@ -4232,7 +4232,7 @@ void tst_qqmlecmascript::importScripts()
QObject *object = component.create();
if (!errorMessage.isEmpty()) {
- QVERIFY(object == 0);
+ QVERIFY(!object);
} else {
QVERIFY(object != 0);
@@ -4685,7 +4685,7 @@ void tst_qqmlecmascript::propertyChangeSlots()
QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
object = e1.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
delete object;
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
@@ -4693,7 +4693,7 @@ void tst_qqmlecmascript::propertyChangeSlots()
expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
object = e2.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
delete object;
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
@@ -4701,7 +4701,7 @@ void tst_qqmlecmascript::propertyChangeSlots()
expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
object = e3.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
delete object;
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
@@ -4709,7 +4709,7 @@ void tst_qqmlecmascript::propertyChangeSlots()
expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
object = e4.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
delete object;
}
@@ -5007,6 +5007,12 @@ void tst_qqmlecmascript::propertyVarCircular()
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignCircular"); // cause assignment and gc
+ {
+ QCOMPARE(object->property("canaryInt"), QVariant(5));
+ QVariant canaryResourceVariant = object->property("canaryResource");
+ QVERIFY(canaryResourceVariant.isValid());
+ }
+
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
QCoreApplication::processEvents();
QCOMPARE(object->property("canaryInt"), QVariant(5));
@@ -5703,9 +5709,10 @@ void tst_qqmlecmascript::deletedEngine()
delete engine;
- QCOMPARE(object->property("a").toInt(), 117);
+ QCOMPARE(object->property("a").toInt(), 0);
object->setProperty("b", QVariant(10));
- QCOMPARE(object->property("a").toInt(), 117);
+ object->setProperty("b", QVariant());
+ QCOMPARE(object->property("a").toInt(), 0);
delete object;
}
@@ -5747,10 +5754,10 @@ void tst_qqmlecmascript::variants()
QObject *object = component.create();
QVERIFY(object != 0);
- QVERIFY(object->property("undefinedVariant").type() == QVariant::Invalid);
- QVERIFY(object->property("nullVariant").type() == (int)QMetaType::VoidStar);
- QVERIFY(object->property("intVariant").type() == QVariant::Int);
- QVERIFY(object->property("doubleVariant").type() == QVariant::Double);
+ QCOMPARE(object->property("undefinedVariant").type(), QVariant::Invalid);
+ QCOMPARE(int(object->property("nullVariant").type()), int(QMetaType::VoidStar));
+ QCOMPARE(object->property("intVariant").type(), QVariant::Int);
+ QCOMPARE(object->property("doubleVariant").type(), QVariant::Double);
QVariant result;
QMetaObject::invokeMethod(object, "checkNull", Q_RETURN_ARG(QVariant, result));
@@ -5801,7 +5808,7 @@ void tst_qqmlecmascript::qtcreatorbug_1289()
delete nested;
nested = qvariant_cast<QObject *>(o->property("object"));
- QVERIFY(nested == 0);
+ QVERIFY(!nested);
// If the bug is present, the next line will crash
delete o;
@@ -5848,7 +5855,7 @@ void tst_qqmlecmascript::canAssignNullToQObject()
o->setProperty("runTest", true);
- QVERIFY(o->objectProperty() == 0);
+ QVERIFY(!o->objectProperty());
delete o;
}
@@ -5859,7 +5866,7 @@ void tst_qqmlecmascript::canAssignNullToQObject()
MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(o != 0);
- QVERIFY(o->objectProperty() == 0);
+ QVERIFY(!o->objectProperty());
delete o;
}
@@ -6064,7 +6071,7 @@ void tst_qqmlecmascript::include()
o->setProperty("serverBaseUrl", server.baseUrl().toString());
component.completeCreate();
- QTRY_VERIFY(o->property("done").toBool() == true);
+ QTRY_VERIFY(o->property("done").toBool());
QCOMPARE(o->property("test1").toBool(), true);
QCOMPARE(o->property("test2").toBool(), true);
@@ -6108,8 +6115,8 @@ void tst_qqmlecmascript::includeRemoteSuccess()
o->setProperty("serverBaseUrl", server.baseUrl().toString());
component.completeCreate();
- QTRY_VERIFY(o->property("done").toBool() == true);
- QTRY_VERIFY(o->property("done2").toBool() == true);
+ QTRY_VERIFY(o->property("done").toBool());
+ QTRY_VERIFY(o->property("done2").toBool());
QCOMPARE(o->property("test1").toBool(), true);
QCOMPARE(o->property("test2").toBool(), true);
@@ -6132,7 +6139,7 @@ void tst_qqmlecmascript::signalHandlers()
QObject *o = component.create();
QVERIFY(o != 0);
- QVERIFY(o->property("count").toInt() == 0);
+ QCOMPARE(o->property("count").toInt(), 0);
QMetaObject::invokeMethod(o, "testSignalCall");
QCOMPARE(o->property("count").toInt(), 1);
@@ -6140,7 +6147,7 @@ void tst_qqmlecmascript::signalHandlers()
QCOMPARE(o->property("count").toInt(), 1);
QCOMPARE(o->property("errorString").toString(), QLatin1String("TypeError: Property 'onTestSignal' of object [object Object] is not a function"));
- QVERIFY(o->property("funcCount").toInt() == 0);
+ QCOMPARE(o->property("funcCount").toInt(), 0);
QMetaObject::invokeMethod(o, "testSignalConnection");
QCOMPARE(o->property("funcCount").toInt(), 1);
@@ -6684,7 +6691,7 @@ void tst_qqmlecmascript::incrDecrSemicolon_error1()
{
QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon_error1.qml"));
QObject *object = component.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
}
void tst_qqmlecmascript::unaryExpression()
@@ -7032,7 +7039,7 @@ void tst_qqmlecmascript::invokableWithQObjectDerived()
QObject *object = component.create();
QVERIFY(object != 0);
- QVERIFY(object->property("result").value<bool>() == true);
+ QVERIFY(object->property("result").value<bool>());
delete object;
}
@@ -7344,7 +7351,7 @@ void tst_qqmlecmascript::sequenceSort()
QVariant q;
QMetaObject::invokeMethod(object, function.toAscii().constData(), Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, useComparer));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
delete object;
}
@@ -7360,10 +7367,10 @@ void tst_qqmlecmascript::dateParse()
QVariant q;
QMetaObject::invokeMethod(object, "test_is_invalid_jsDateTime", Q_RETURN_ARG(QVariant, q));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
QMetaObject::invokeMethod(object, "test_is_invalid_qtDateTime", Q_RETURN_ARG(QVariant, q));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
QMetaObject::invokeMethod(object, "test_rfc2822_date", Q_RETURN_ARG(QVariant, q));
QCOMPARE(q.toLongLong(), 1379512851000LL);
@@ -7381,7 +7388,7 @@ void tst_qqmlecmascript::utcDate()
QVariant q;
QVariant val = QString::fromLatin1("2014-07-16T23:30:31");
QMetaObject::invokeMethod(object, "check_utc", Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, val));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
}
void tst_qqmlecmascript::negativeYear()
@@ -7478,7 +7485,7 @@ void tst_qqmlecmascript::stringParsing()
file = file.arg(i);
QQmlComponent component(&engine, testFileUrl(file));
QObject *object = component.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
}
}
@@ -7491,7 +7498,7 @@ void tst_qqmlecmascript::push_and_shift()
" array.push(5); array.unshift(5); array.push(5);"
"}"
"array.length;";
- QVERIFY(e.evaluate(program).toNumber() == 30000);
+ QCOMPARE(e.evaluate(program).toNumber(), double(30000));
}
void tst_qqmlecmascript::qtbug_32801()
@@ -7611,13 +7618,13 @@ void tst_qqmlecmascript::miscTypeTest()
QVariant q;
QMetaObject::invokeMethod(object, "test_invalid_url_equal", Q_RETURN_ARG(QVariant, q));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
QMetaObject::invokeMethod(object, "test_invalid_url_strictequal", Q_RETURN_ARG(QVariant, q));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
QMetaObject::invokeMethod(object, "test_valid_url_equal", Q_RETURN_ARG(QVariant, q));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
QMetaObject::invokeMethod(object, "test_valid_url_strictequal", Q_RETURN_ARG(QVariant, q));
- QVERIFY(q.toBool() == true);
+ QVERIFY(q.toBool());
delete object;
}
@@ -7665,7 +7672,7 @@ void tst_qqmlecmascript::singletonWithEnum()
qDebug() << component.errors().first().toString();
QVERIFY(!obj.isNull());
QVariant prop = obj->property("testValue");
- QVERIFY(prop.type() == QVariant::Int);
+ QCOMPARE(prop.type(), QVariant::Int);
QCOMPARE(prop.toInt(), int(SingletonWithEnum::TestValue));
}
@@ -7677,7 +7684,7 @@ void tst_qqmlecmascript::lazyBindingEvaluation()
qDebug() << component.errors().first().toString();
QVERIFY(!obj.isNull());
QVariant prop = obj->property("arrayLength");
- QVERIFY(prop.type() == QVariant::Int);
+ QCOMPARE(prop.type(), QVariant::Int);
QCOMPARE(prop.toInt(), 2);
}
@@ -7688,7 +7695,7 @@ void tst_qqmlecmascript::varPropertyAccessOnObjectWithInvalidContext()
if (obj.isNull())
qDebug() << component.errors().first().toString();
QVERIFY(!obj.isNull());
- QVERIFY(obj->property("success") == true);
+ QVERIFY(obj->property("success").toBool());
}
void tst_qqmlecmascript::importedScriptsAccessOnObjectWithInvalidContext()
@@ -7698,7 +7705,7 @@ void tst_qqmlecmascript::importedScriptsAccessOnObjectWithInvalidContext()
if (obj.isNull())
qDebug() << component.errors().first().toString();
QVERIFY(!obj.isNull());
- QTRY_VERIFY(obj->property("success") == true);
+ QTRY_VERIFY(obj->property("success").toBool());
}
void tst_qqmlecmascript::importedScriptsWithoutQmlMode()
@@ -7708,7 +7715,7 @@ void tst_qqmlecmascript::importedScriptsWithoutQmlMode()
if (obj.isNull())
qDebug() << component.errors().first().toString();
QVERIFY(!obj.isNull());
- QTRY_VERIFY(obj->property("success") == true);
+ QTRY_VERIFY(obj->property("success").toBool());
}
void tst_qqmlecmascript::contextObjectOnLazyBindings()
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index eac648ef15..cb911d0115 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -90,7 +90,7 @@ void tst_qqmlengine::rootContext()
QVERIFY(engine.rootContext());
QCOMPARE(engine.rootContext()->engine(), &engine);
- QVERIFY(engine.rootContext()->parentContext() == 0);
+ QVERIFY(!engine.rootContext()->parentContext());
}
class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
@@ -119,8 +119,9 @@ void tst_qqmlengine::networkAccessManager()
engine = new QQmlEngine;
NetworkAccessManagerFactory factory;
engine->setNetworkAccessManagerFactory(&factory);
- QVERIFY(engine->networkAccessManagerFactory() == &factory);
- QVERIFY(engine->networkAccessManager() == factory.manager);
+ QCOMPARE(engine->networkAccessManagerFactory(), &factory);
+ QNetworkAccessManager *engineNam = engine->networkAccessManager(); // calls NetworkAccessManagerFactory::create()
+ QCOMPARE(engineNam, factory.manager);
delete engine;
}
@@ -184,7 +185,7 @@ void tst_qqmlengine::baseUrl()
dir.cdUp();
QVERIFY(dir != QDir::current());
QDir::setCurrent(dir.path());
- QVERIFY(QDir::current() == dir);
+ QCOMPARE(QDir::current(), dir);
QUrl cwd2 = QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
QCOMPARE(engine.baseUrl(), cwd2);
@@ -200,11 +201,11 @@ void tst_qqmlengine::contextForObject()
QQmlEngine *engine = new QQmlEngine;
// Test null-object
- QVERIFY(QQmlEngine::contextForObject(0) == 0);
+ QVERIFY(!QQmlEngine::contextForObject(0));
// Test an object with no context
QObject object;
- QVERIFY(QQmlEngine::contextForObject(&object) == 0);
+ QVERIFY(!QQmlEngine::contextForObject(&object));
// Test setting null-object
QQmlEngine::setContextForObject(0, engine->rootContext());
@@ -214,18 +215,18 @@ void tst_qqmlengine::contextForObject()
// Test setting context
QQmlEngine::setContextForObject(&object, engine->rootContext());
- QVERIFY(QQmlEngine::contextForObject(&object) == engine->rootContext());
+ QCOMPARE(QQmlEngine::contextForObject(&object), engine->rootContext());
QQmlContext context(engine->rootContext());
// Try changing context
QTest::ignoreMessage(QtWarningMsg, "QQmlEngine::setContextForObject(): Object already has a QQmlContext");
QQmlEngine::setContextForObject(&object, &context);
- QVERIFY(QQmlEngine::contextForObject(&object) == engine->rootContext());
+ QCOMPARE(QQmlEngine::contextForObject(&object), engine->rootContext());
// Delete context
delete engine; engine = 0;
- QVERIFY(QQmlEngine::contextForObject(&object) == 0);
+ QVERIFY(!QQmlEngine::contextForObject(&object));
}
void tst_qqmlengine::offlineStoragePath()
@@ -446,7 +447,7 @@ void tst_qqmlengine::failedCompilation()
QQmlComponent component(&engine, testFileUrl(file));
QVERIFY(!component.isReady());
QScopedPointer<QObject> object(component.create());
- QVERIFY(object == 0);
+ QVERIFY(object.isNull());
engine.collectGarbage();
engine.trimComponentCache();
@@ -470,7 +471,7 @@ void tst_qqmlengine::outputWarningsToStandardError()
QQmlComponent c(&engine);
c.setData("import QtQuick 2.0; QtObject { property int a: undefined }", QUrl());
- QVERIFY(c.isReady() == true);
+ QVERIFY(c.isReady());
QQmlTestMessageHandler messageHandler;
diff --git a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
index e381976448..d9838a4941 100644
--- a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
+++ b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
@@ -140,7 +140,7 @@ void tst_qqmlexpression::expressionFromDataComponent()
QQmlExpression expression(object->scriptString());
QVariant result = expression.evaluate();
- QVERIFY(result.type() == QVariant::String);
+ QCOMPARE(result.type(), QVariant::String);
QCOMPARE(result.toString(), QStringLiteral("success"));
}
diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
index 26092595d9..4f559b0d33 100644
--- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
+++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
@@ -148,7 +148,7 @@ void tst_qqmlincubator::objectDeleted()
component.create(incubator);
QCOMPARE(incubator.status(), QQmlIncubator::Loading);
- QVERIFY(SelfRegisteringType::me() == 0);
+ QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringOuterType::me() == 0 && incubator.isLoading()) {
bool b = false;
@@ -172,7 +172,7 @@ void tst_qqmlincubator::objectDeleted()
QVERIFY(incubator.isError());
VERIFY_ERRORS(incubator, "objectDeleted.errors.txt");
- QVERIFY(incubator.object() == 0);
+ QVERIFY(!incubator.object());
}
QVERIFY(SelfRegisteringOuterType::beenDeleted);
}
@@ -236,7 +236,7 @@ void tst_qqmlincubator::clear()
incubator.clear();
QVERIFY(incubator.isNull());
- QVERIFY(incubator.object() == 0);
+ QVERIFY(!incubator.object());
QVERIFY(!obj.isNull());
delete obj;
@@ -413,7 +413,7 @@ void tst_qqmlincubator::clearDuringCompletion()
component.create(incubator);
QCOMPARE(incubator.status(), QQmlIncubator::Loading);
- QVERIFY(CompletionRegisteringType::me() == 0);
+ QVERIFY(!CompletionRegisteringType::me());
while (CompletionRegisteringType::me() == 0 && incubator.isLoading()) {
bool b = false;
@@ -622,7 +622,7 @@ void tst_qqmlincubator::asynchronousIfNested()
component.create(incubator);
QVERIFY(incubator.isLoading());
- QVERIFY(SelfRegisteringType::me() == 0);
+ QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
bool b = false;
controller.incubateWhile(&b);
@@ -741,7 +741,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNested()
component.create(incubator);
QVERIFY(incubator.isLoading());
- QVERIFY(SelfRegisteringType::me() == 0);
+ QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
bool b = false;
@@ -855,7 +855,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted()
component.create(incubator);
QVERIFY(incubator.isLoading());
- QVERIFY(SelfRegisteringType::me() == 0);
+ QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
bool b = false;
@@ -983,7 +983,7 @@ void tst_qqmlincubator::chainedAsynchronousClear()
component.create(incubator);
QVERIFY(incubator.isLoading());
- QVERIFY(SelfRegisteringType::me() == 0);
+ QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
bool b = false;
@@ -1106,7 +1106,7 @@ void tst_qqmlincubator::selfDelete()
component.create(*incubator);
QCOMPARE(incubator->QQmlIncubator::status(), QQmlIncubator::Loading);
- QVERIFY(SelfRegisteringType::me() == 0);
+ QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == 0 && incubator->isLoading()) {
bool b = false;
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 08da779d90..152b7510d2 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -55,6 +55,10 @@
#include "../../shared/util.h"
+#if defined(Q_OS_MAC)
+#include <unistd.h>
+#endif
+
DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
static inline bool isCaseSensitiveFileSystem(const QString &path) {
@@ -328,7 +332,7 @@ void tst_qqmllanguage::insertedSemicolon()
if(create) {
QObject *object = component.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
}
VERIFY_ERRORS(errorFile.toLatin1().constData());
@@ -550,7 +554,7 @@ void tst_qqmllanguage::errors()
if (create) {
QObject *object = component.create();
- QVERIFY(object == 0);
+ QVERIFY(!object);
}
VERIFY_ERRORS(errorFile.toLatin1().constData());
@@ -580,7 +584,7 @@ void tst_qqmllanguage::interfaceProperty()
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != 0);
QVERIFY(object->interface());
- QVERIFY(object->interface()->id == 913);
+ QCOMPARE(object->interface()->id, 913);
}
void tst_qqmllanguage::interfaceQList()
@@ -589,9 +593,9 @@ void tst_qqmllanguage::interfaceQList()
VERIFY_ERRORS(0);
MyContainer *container= qobject_cast<MyContainer*>(component.create());
QVERIFY(container != 0);
- QVERIFY(container->getQListInterfaces()->count() == 2);
+ QCOMPARE(container->getQListInterfaces()->count(), 2);
for(int ii = 0; ii < 2; ++ii)
- QVERIFY(container->getQListInterfaces()->at(ii)->id == 913);
+ QCOMPARE(container->getQListInterfaces()->at(ii)->id, 913);
}
void tst_qqmllanguage::assignObjectToSignal()
@@ -630,7 +634,7 @@ void tst_qqmllanguage::assignQmlComponent()
VERIFY_ERRORS(0);
MyContainer *object = qobject_cast<MyContainer *>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->getChildren()->count() == 1);
+ QCOMPARE(object->getChildren()->count(), 1);
QObject *child = object->getChildren()->at(0);
QCOMPARE(child->property("x"), QVariant(10));
QCOMPARE(child->property("y"), QVariant(11));
@@ -722,17 +726,17 @@ void tst_qqmllanguage::assignLiteralToVariant()
QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
QCOMPARE(object->property("test12").userType(), (int)QVariant::Vector4D);
- QVERIFY(object->property("test1") == QVariant(1));
- QVERIFY(object->property("test2") == QVariant((double)1.7));
+ QCOMPARE(object->property("test1"), QVariant(1));
+ QCOMPARE(object->property("test2"), QVariant((double)1.7));
QVERIFY(object->property("test3") == QVariant(QString(QLatin1String("Hello world!"))));
- QVERIFY(object->property("test4") == QVariant(QColor::fromRgb(0xFF008800)));
+ QCOMPARE(object->property("test4"), QVariant(QColor::fromRgb(0xFF008800)));
QVERIFY(object->property("test5") == QVariant(QRectF(10, 10, 10, 10)));
QVERIFY(object->property("test6") == QVariant(QPointF(10, 10)));
QVERIFY(object->property("test7") == QVariant(QSizeF(10, 10)));
QVERIFY(object->property("test8") == QVariant(QVector3D(100, 100, 100)));
- QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800"))));
- QVERIFY(object->property("test10") == QVariant(bool(true)));
- QVERIFY(object->property("test11") == QVariant(bool(false)));
+ QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
+ QCOMPARE(object->property("test10"), QVariant(bool(true)));
+ QCOMPARE(object->property("test11"), QVariant(bool(false)));
QVERIFY(object->property("test12") == QVariant(QVector4D(100, 100, 100, 100)));
delete object;
@@ -1170,7 +1174,7 @@ void tst_qqmllanguage::customParserTypes()
VERIFY_ERRORS(0);
QObject *object = component.create();
QVERIFY(object != 0);
- QVERIFY(object->property("count") == QVariant(2));
+ QCOMPARE(object->property("count"), QVariant(2));
}
// Tests that the root item can be a custom component
@@ -1352,7 +1356,7 @@ void tst_qqmllanguage::dynamicObjectProperties()
QObject *object = component.create();
QVERIFY(object != 0);
- QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
+ QCOMPARE(object->property("objectProperty"), qVariantFromValue((QObject*)0));
QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
}
{
@@ -1661,7 +1665,7 @@ void tst_qqmllanguage::aliasProperties()
v = object->property("otherAlias");
QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
o = qvariant_cast<MyQmlObject*>(v);
- QVERIFY(o == 0);
+ QVERIFY(!o);
delete object;
}
@@ -1691,7 +1695,7 @@ void tst_qqmllanguage::aliasProperties()
QVERIFY(object2 != 0);
QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
- QVERIFY(alias == object2);
+ QCOMPARE(alias, object2);
delete object1;
@@ -1700,7 +1704,7 @@ void tst_qqmllanguage::aliasProperties()
void *a[] = { &alias2, 0, &status };
QMetaObject::metacall(object, QMetaObject::ReadProperty,
object->metaObject()->indexOfProperty("aliasedObject"), a);
- QVERIFY(alias2 == 0);
+ QVERIFY(!alias2);
}
// Simple composite type
@@ -2106,50 +2110,50 @@ void tst_qqmllanguage::scriptStringComparison()
const qreal n = 12.345;
bool ok;
- QVERIFY(object2->scriptProperty().stringLiteral() == s);
+ QCOMPARE(object2->scriptProperty().stringLiteral(), s);
QVERIFY(object3->scriptProperty().numberLiteral(&ok) == n && ok);
- QVERIFY(object1->scriptProperty() == object1->scriptProperty());
- QVERIFY(object2->scriptProperty() == object2->scriptProperty());
- QVERIFY(object3->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object1->scriptProperty(), object1->scriptProperty());
+ QCOMPARE(object2->scriptProperty(), object2->scriptProperty());
+ QCOMPARE(object3->scriptProperty(), object3->scriptProperty());
QVERIFY(object2->scriptProperty() != object3->scriptProperty());
QVERIFY(object1->scriptProperty() != object2->scriptProperty());
QVERIFY(object1->scriptProperty() != object3->scriptProperty());
func.callWithInstance(inst2, QJSValueList() << n);
- QVERIFY(object2->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object2->scriptProperty(), object3->scriptProperty());
func.callWithInstance(inst2, QJSValueList() << s);
QVERIFY(object2->scriptProperty() != object3->scriptProperty());
func.callWithInstance(inst3, QJSValueList() << s);
- QVERIFY(object2->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object2->scriptProperty(), object3->scriptProperty());
func.callWithInstance(inst2, QJSValueList() << QJSValue::UndefinedValue);
QVERIFY(object2->scriptProperty() != object3->scriptProperty());
func.callWithInstance(inst3, QJSValueList() << QJSValue::UndefinedValue);
- QVERIFY(object2->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object2->scriptProperty(), object3->scriptProperty());
func.callWithInstance(inst2, QJSValueList() << QJSValue::NullValue);
QVERIFY(object2->scriptProperty() != object3->scriptProperty());
func.callWithInstance(inst3, QJSValueList() << QJSValue::NullValue);
- QVERIFY(object2->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object2->scriptProperty(), object3->scriptProperty());
func.callWithInstance(inst2, QJSValueList() << false);
QVERIFY(object2->scriptProperty() != object3->scriptProperty());
func.callWithInstance(inst3, QJSValueList() << false);
- QVERIFY(object2->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object2->scriptProperty(), object3->scriptProperty());
func.callWithInstance(inst2, QJSValueList() << true);
QVERIFY(object2->scriptProperty() != object3->scriptProperty());
func.callWithInstance(inst3, QJSValueList() << true);
- QVERIFY(object2->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object2->scriptProperty(), object3->scriptProperty());
QVERIFY(object1->scriptProperty() != object2->scriptProperty());
object2->setScriptProperty(object1->scriptProperty());
- QVERIFY(object1->scriptProperty() == object2->scriptProperty());
+ QCOMPARE(object1->scriptProperty(), object2->scriptProperty());
QVERIFY(object1->scriptProperty() != object3->scriptProperty());
func.callWithInstance(inst3, QJSValueList() << engine.toScriptValue(object1->scriptProperty()));
- QVERIFY(object1->scriptProperty() == object3->scriptProperty());
+ QCOMPARE(object1->scriptProperty(), object3->scriptProperty());
// While this are two instances of the same object they are still considered different
// because the (none literal) script string may access variables which have different
@@ -3250,7 +3254,7 @@ void tst_qqmllanguage::registrationOrder()
QObject *o = component.create();
QVERIFY(o != 0);
- QVERIFY(o->metaObject() == &MyVersion2Class::staticMetaObject);
+ QCOMPARE(o->metaObject(), &MyVersion2Class::staticMetaObject);
delete o;
}
@@ -3644,7 +3648,7 @@ void tst_qqmllanguage::compositeSingletonSameEngine()
QVERIFY(s2 != 0);
QCOMPARE(s2->property("testProp2"), QVariant(13));
- QVERIFY(s1 == s2);
+ QCOMPARE(s1, s2);
}
// Checks that the addresses of the composite singletons used in different
@@ -3693,7 +3697,7 @@ void tst_qqmllanguage::compositeSingletonQualifiedNamespace()
getSingletonInstance(engine, "singletonTest5a.qml", "singletonInstance", &s2);
QVERIFY(s2 != 0);
- QVERIFY(s1 == s2);
+ QCOMPARE(s1, s2);
}
// Loads a singleton from a module
@@ -3719,7 +3723,7 @@ void tst_qqmllanguage::compositeSingletonModule()
getSingletonInstance(engine, "singletonTest6a.qml", "singletonInstance", &s2);
QVERIFY(s2 != 0);
- QVERIFY(s1 == s2);
+ QCOMPARE(s1, s2);
}
// Loads a singleton from a module with a higher version
@@ -3745,7 +3749,7 @@ void tst_qqmllanguage::compositeSingletonModuleVersioned()
getSingletonInstance(engine, "singletonTest7a.qml", "singletonInstance", &s2);
QVERIFY(s2 != 0);
- QVERIFY(s1 == s2);
+ QCOMPARE(s1, s2);
}
// Loads a singleton from a module with a qualified namespace
@@ -3771,7 +3775,7 @@ void tst_qqmllanguage::compositeSingletonModuleQualified()
getSingletonInstance(engine, "singletonTest8a.qml", "singletonInstance", &s2);
QVERIFY(s2 != 0);
- QVERIFY(s1 == s2);
+ QCOMPARE(s1, s2);
}
// Tries to instantiate a type with a pragma Singleton and fails
@@ -3995,7 +3999,7 @@ void tst_qqmllanguage::propertyCacheInSync()
QVERIFY(ddata);
QVERIFY(ddata->propertyCache);
// Those always have to be in sync and correct.
- QVERIFY(ddata->propertyCache == vmemoCache);
+ QCOMPARE(ddata->propertyCache, vmemoCache);
QCOMPARE(anchors->property("margins").toInt(), 50);
}
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 4d76fc4fba..5c252013ea 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -642,7 +642,7 @@ void tst_qqmllistmodel::enumerate()
}
}
- QVERIFY(matchCount == expectedStringCount);
+ QCOMPARE(matchCount, expectedStringCount);
delete item;
}
@@ -1296,7 +1296,7 @@ void tst_qqmllistmodel::datetime()
QQmlExpression e(engine.rootContext(), &model, qml);
QVariant result = e.evaluate();
QDateTime dtResult = result.toDateTime();
- QVERIFY(expected == dtResult);
+ QCOMPARE(expected, dtResult);
}
class RowTester : public QObject
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
index 5bf75d41d4..0ad2963265 100644
--- a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
+++ b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
@@ -647,15 +647,15 @@ void tst_qqmllistmodelworkerscript::worker_sync()
QQuickItem *item = createWorkerTest(&eng, &component, &model);
QVERIFY(item != 0);
- QVERIFY(model.count() == 0);
+ QCOMPARE(model.count(), 0);
QVERIFY(QMetaObject::invokeMethod(item, "addItem0"));
- QVERIFY(model.count() == 2);
+ QCOMPARE(model.count(), 2);
QVariant childData = model.data(0, 0);
QQmlListModel *childModel = qobject_cast<QQmlListModel *>(childData.value<QObject *>());
QVERIFY(childModel);
- QVERIFY(childModel->count() == 1);
+ QCOMPARE(childModel->count(), 1);
QSignalSpy spyModelInserted(&model, SIGNAL(rowsInserted(QModelIndex,int,int)));
QSignalSpy spyChildInserted(childModel, SIGNAL(rowsInserted(QModelIndex,int,int)));
@@ -663,34 +663,34 @@ void tst_qqmllistmodelworkerscript::worker_sync()
QVERIFY(QMetaObject::invokeMethod(item, "addItemViaWorker"));
waitForWorker(item);
- QVERIFY(model.count() == 2);
- QVERIFY(childModel->count() == 1);
- QVERIFY(spyModelInserted.count() == 0);
- QVERIFY(spyChildInserted.count() == 0);
+ QCOMPARE(model.count(), 2);
+ QCOMPARE(childModel->count(), 1);
+ QCOMPARE(spyModelInserted.count(), 0);
+ QCOMPARE(spyChildInserted.count(), 0);
QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
waitForWorker(item);
- QVERIFY(model.count() == 2);
- QVERIFY(childModel->count() == 2);
- QVERIFY(spyModelInserted.count() == 0);
- QVERIFY(spyChildInserted.count() == 1);
+ QCOMPARE(model.count(), 2);
+ QCOMPARE(childModel->count(), 2);
+ QCOMPARE(spyModelInserted.count(), 0);
+ QCOMPARE(spyChildInserted.count(), 1);
QVERIFY(QMetaObject::invokeMethod(item, "addItemViaWorker"));
waitForWorker(item);
- QVERIFY(model.count() == 2);
- QVERIFY(childModel->count() == 2);
- QVERIFY(spyModelInserted.count() == 0);
- QVERIFY(spyChildInserted.count() == 1);
+ QCOMPARE(model.count(), 2);
+ QCOMPARE(childModel->count(), 2);
+ QCOMPARE(spyModelInserted.count(), 0);
+ QCOMPARE(spyChildInserted.count(), 1);
QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
waitForWorker(item);
- QVERIFY(model.count() == 2);
- QVERIFY(childModel->count() == 3);
- QVERIFY(spyModelInserted.count() == 0);
- QVERIFY(spyChildInserted.count() == 2);
+ QCOMPARE(model.count(), 2);
+ QCOMPARE(childModel->count(), 3);
+ QCOMPARE(spyModelInserted.count(), 0);
+ QCOMPARE(spyChildInserted.count(), 2);
delete item;
qApp->processEvents();
@@ -714,24 +714,24 @@ void tst_qqmllistmodelworkerscript::worker_remove_element()
QSignalSpy spyModelRemoved(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
- QVERIFY(model.count() == 0);
- QVERIFY(spyModelRemoved.count() == 0);
+ QCOMPARE(model.count(), 0);
+ QCOMPARE(spyModelRemoved.count(), 0);
QVERIFY(QMetaObject::invokeMethod(item, "addItem"));
- QVERIFY(model.count() == 1);
+ QCOMPARE(model.count(), 1);
QVERIFY(QMetaObject::invokeMethod(item, "removeItemViaWorker"));
waitForWorker(item);
- QVERIFY(model.count() == 1);
- QVERIFY(spyModelRemoved.count() == 0);
+ QCOMPARE(model.count(), 1);
+ QCOMPARE(spyModelRemoved.count(), 0);
QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
waitForWorker(item);
- QVERIFY(model.count() == 0);
- QVERIFY(spyModelRemoved.count() == 1);
+ QCOMPARE(model.count(), 0);
+ QCOMPARE(spyModelRemoved.count(), 1);
delete item;
qApp->processEvents();
@@ -747,7 +747,7 @@ void tst_qqmllistmodelworkerscript::worker_remove_element()
QVERIFY(QMetaObject::invokeMethod(item, "addItem"));
- QVERIFY(model->count() == 1);
+ QCOMPARE(model->count(), 1);
QVERIFY(QMetaObject::invokeMethod(item, "removeItemViaWorker"));
QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
@@ -777,24 +777,24 @@ void tst_qqmllistmodelworkerscript::worker_remove_list()
QSignalSpy spyModelRemoved(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
- QVERIFY(model.count() == 0);
- QVERIFY(spyModelRemoved.count() == 0);
+ QCOMPARE(model.count(), 0);
+ QCOMPARE(spyModelRemoved.count(), 0);
QVERIFY(QMetaObject::invokeMethod(item, "addList"));
- QVERIFY(model.count() == 1);
+ QCOMPARE(model.count(), 1);
QVERIFY(QMetaObject::invokeMethod(item, "removeListViaWorker"));
waitForWorker(item);
- QVERIFY(model.count() == 1);
- QVERIFY(spyModelRemoved.count() == 0);
+ QCOMPARE(model.count(), 1);
+ QCOMPARE(spyModelRemoved.count(), 0);
QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
waitForWorker(item);
- QVERIFY(model.count() == 0);
- QVERIFY(spyModelRemoved.count() == 1);
+ QCOMPARE(model.count(), 0);
+ QCOMPARE(spyModelRemoved.count(), 1);
delete item;
qApp->processEvents();
diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
index b5963e2f71..274f292c38 100644
--- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
+++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
@@ -98,7 +98,7 @@ void tst_qqmllistreference::qmllistreference()
TestType tt;
QQmlListReference r(&tt, "data");
- QVERIFY(r.isValid() == true);
+ QVERIFY(r.isValid());
QCOMPARE(r.count(), 0);
tt.data.append(&tt);
@@ -112,52 +112,52 @@ void tst_qqmllistreference::qmllistreference_invalid()
// Invalid
{
QQmlListReference r;
- QVERIFY(r.isValid() == false);
- QVERIFY(r.object() == 0);
- QVERIFY(r.listElementType() == 0);
- QVERIFY(r.canAt() == false);
- QVERIFY(r.canClear() == false);
- QVERIFY(r.canCount() == false);
- QVERIFY(r.append(0) == false);
- QVERIFY(r.at(10) == 0);
- QVERIFY(r.clear() == false);
- QVERIFY(r.count() == 0);
- QVERIFY(r.isReadable() == false);
- QVERIFY(r.isManipulable() == false);
+ QVERIFY(!r.isValid());
+ QVERIFY(!r.object());
+ QVERIFY(!r.listElementType());
+ QVERIFY(!r.canAt());
+ QVERIFY(!r.canClear());
+ QVERIFY(!r.canCount());
+ QVERIFY(!r.append(0));
+ QVERIFY(!r.at(10));
+ QVERIFY(!r.clear());
+ QCOMPARE(r.count(), 0);
+ QVERIFY(!r.isReadable());
+ QVERIFY(!r.isManipulable());
}
// Non-property
{
QQmlListReference r(&tt, "blah");
- QVERIFY(r.isValid() == false);
- QVERIFY(r.object() == 0);
- QVERIFY(r.listElementType() == 0);
- QVERIFY(r.canAt() == false);
- QVERIFY(r.canClear() == false);
- QVERIFY(r.canCount() == false);
- QVERIFY(r.append(0) == false);
- QVERIFY(r.at(10) == 0);
- QVERIFY(r.clear() == false);
- QVERIFY(r.count() == 0);
- QVERIFY(r.isReadable() == false);
- QVERIFY(r.isManipulable() == false);
+ QVERIFY(!r.isValid());
+ QVERIFY(!r.object());
+ QVERIFY(!r.listElementType());
+ QVERIFY(!r.canAt());
+ QVERIFY(!r.canClear());
+ QVERIFY(!r.canCount());
+ QVERIFY(!r.append(0));
+ QVERIFY(!r.at(10));
+ QVERIFY(!r.clear());
+ QCOMPARE(r.count(), 0);
+ QVERIFY(!r.isReadable());
+ QVERIFY(!r.isManipulable());
}
// Non-list property
{
QQmlListReference r(&tt, "intProperty");
- QVERIFY(r.isValid() == false);
- QVERIFY(r.object() == 0);
- QVERIFY(r.listElementType() == 0);
- QVERIFY(r.canAt() == false);
- QVERIFY(r.canClear() == false);
- QVERIFY(r.canCount() == false);
- QVERIFY(r.append(0) == false);
- QVERIFY(r.at(10) == 0);
- QVERIFY(r.clear() == false);
- QVERIFY(r.count() == 0);
- QVERIFY(r.isReadable() == false);
- QVERIFY(r.isManipulable() == false);
+ QVERIFY(!r.isValid());
+ QVERIFY(!r.object());
+ QVERIFY(!r.listElementType());
+ QVERIFY(!r.canAt());
+ QVERIFY(!r.canClear());
+ QVERIFY(!r.canCount());
+ QVERIFY(!r.append(0));
+ QVERIFY(!r.at(10));
+ QVERIFY(!r.clear());
+ QCOMPARE(r.count(), 0);
+ QVERIFY(!r.isReadable());
+ QVERIFY(!r.isManipulable());
}
}
@@ -167,19 +167,19 @@ void tst_qqmllistreference::isValid()
{
QQmlListReference ref;
- QVERIFY(ref.isValid() == false);
+ QVERIFY(!ref.isValid());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.isValid() == false);
+ QVERIFY(!ref.isValid());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.isValid() == true);
+ QVERIFY(ref.isValid());
delete tt;
- QVERIFY(ref.isValid() == false);
+ QVERIFY(!ref.isValid());
}
}
@@ -189,19 +189,19 @@ void tst_qqmllistreference::object()
{
QQmlListReference ref;
- QVERIFY(ref.object() == 0);
+ QVERIFY(!ref.object());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.object() == 0);
+ QVERIFY(!ref.object());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.object() == tt);
+ QCOMPARE(ref.object(), tt);
delete tt;
- QVERIFY(ref.object() == 0);
+ QVERIFY(!ref.object());
}
}
@@ -211,19 +211,19 @@ void tst_qqmllistreference::listElementType()
{
QQmlListReference ref;
- QVERIFY(ref.listElementType() == 0);
+ QVERIFY(!ref.listElementType());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.listElementType() == 0);
+ QVERIFY(!ref.listElementType());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.listElementType() == &TestType::staticMetaObject);
+ QCOMPARE(ref.listElementType(), &TestType::staticMetaObject);
delete tt;
- QVERIFY(ref.listElementType() == 0);
+ QVERIFY(!ref.listElementType());
}
}
@@ -233,26 +233,26 @@ void tst_qqmllistreference::canAppend()
{
QQmlListReference ref;
- QVERIFY(ref.canAppend() == false);
+ QVERIFY(!ref.canAppend());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.canAppend() == false);
+ QVERIFY(!ref.canAppend());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.canAppend() == true);
+ QVERIFY(ref.canAppend());
delete tt;
- QVERIFY(ref.canAppend() == false);
+ QVERIFY(!ref.canAppend());
}
{
TestType tt;
tt.property.append = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.canAppend() == false);
+ QVERIFY(!ref.canAppend());
}
}
@@ -262,26 +262,26 @@ void tst_qqmllistreference::canAt()
{
QQmlListReference ref;
- QVERIFY(ref.canAt() == false);
+ QVERIFY(!ref.canAt());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.canAt() == false);
+ QVERIFY(!ref.canAt());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.canAt() == true);
+ QVERIFY(ref.canAt());
delete tt;
- QVERIFY(ref.canAt() == false);
+ QVERIFY(!ref.canAt());
}
{
TestType tt;
tt.property.at = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.canAt() == false);
+ QVERIFY(!ref.canAt());
}
}
@@ -291,26 +291,26 @@ void tst_qqmllistreference::canClear()
{
QQmlListReference ref;
- QVERIFY(ref.canClear() == false);
+ QVERIFY(!ref.canClear());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.canClear() == false);
+ QVERIFY(!ref.canClear());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.canClear() == true);
+ QVERIFY(ref.canClear());
delete tt;
- QVERIFY(ref.canClear() == false);
+ QVERIFY(!ref.canClear());
}
{
TestType tt;
tt.property.clear = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.canClear() == false);
+ QVERIFY(!ref.canClear());
}
}
@@ -320,26 +320,26 @@ void tst_qqmllistreference::canCount()
{
QQmlListReference ref;
- QVERIFY(ref.canCount() == false);
+ QVERIFY(!ref.canCount());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.canCount() == false);
+ QVERIFY(!ref.canCount());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.canCount() == true);
+ QVERIFY(ref.canCount());
delete tt;
- QVERIFY(ref.canCount() == false);
+ QVERIFY(!ref.canCount());
}
{
TestType tt;
tt.property.count = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.canCount() == false);
+ QVERIFY(!ref.canCount());
}
}
@@ -349,26 +349,26 @@ void tst_qqmllistreference::isReadable()
{
QQmlListReference ref;
- QVERIFY(ref.isReadable() == false);
+ QVERIFY(!ref.isReadable());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.isReadable() == false);
+ QVERIFY(!ref.isReadable());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.isReadable() == true);
+ QVERIFY(ref.isReadable());
delete tt;
- QVERIFY(ref.isReadable() == false);
+ QVERIFY(!ref.isReadable());
}
{
TestType tt;
tt.property.count = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.isReadable() == false);
+ QVERIFY(!ref.isReadable());
}
}
@@ -378,26 +378,26 @@ void tst_qqmllistreference::isManipulable()
{
QQmlListReference ref;
- QVERIFY(ref.isManipulable() == false);
+ QVERIFY(!ref.isManipulable());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.isManipulable() == false);
+ QVERIFY(!ref.isManipulable());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.isManipulable() == true);
+ QVERIFY(ref.isManipulable());
delete tt;
- QVERIFY(ref.isManipulable() == false);
+ QVERIFY(!ref.isManipulable());
}
{
TestType tt;
tt.property.count = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.isManipulable() == false);
+ QVERIFY(!ref.isManipulable());
}
}
@@ -408,35 +408,35 @@ void tst_qqmllistreference::append()
{
QQmlListReference ref;
- QVERIFY(ref.append(tt) == false);
+ QVERIFY(!ref.append(tt));
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.append(tt) == false);
+ QVERIFY(!ref.append(tt));
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.append(tt) == true);
- QVERIFY(tt->data.count() == 1);
- QVERIFY(tt->data.at(0) == tt);
- QVERIFY(ref.append(&object) == false);
- QVERIFY(tt->data.count() == 1);
- QVERIFY(tt->data.at(0) == tt);
- QVERIFY(ref.append(0) == true);
- QVERIFY(tt->data.count() == 2);
- QVERIFY(tt->data.at(0) == tt);
- QVERIFY(tt->data.at(1) == 0);
+ QVERIFY(ref.append(tt));
+ QCOMPARE(tt->data.count(), 1);
+ QCOMPARE(tt->data.at(0), tt);
+ QVERIFY(!ref.append(&object));
+ QCOMPARE(tt->data.count(), 1);
+ QCOMPARE(tt->data.at(0), tt);
+ QVERIFY(ref.append(0));
+ QCOMPARE(tt->data.count(), 2);
+ QCOMPARE(tt->data.at(0), tt);
+ QVERIFY(!tt->data.at(1));
delete tt;
- QVERIFY(ref.append(0) == false);
+ QVERIFY(!ref.append(0));
}
{
TestType tt;
tt.property.append = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.append(&tt) == false);
+ QVERIFY(!ref.append(&tt));
}
}
@@ -449,21 +449,21 @@ void tst_qqmllistreference::at()
{
QQmlListReference ref;
- QVERIFY(ref.at(0) == 0);
+ QVERIFY(!ref.at(0));
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.at(0) == 0);
+ QVERIFY(!ref.at(0));
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.at(0) == tt);
- QVERIFY(ref.at(1) == 0);
- QVERIFY(ref.at(2) == tt);
+ QCOMPARE(ref.at(0), tt);
+ QVERIFY(!ref.at(1));
+ QCOMPARE(ref.at(2), tt);
delete tt;
- QVERIFY(ref.at(0) == 0);
+ QVERIFY(!ref.at(0));
}
{
@@ -471,7 +471,7 @@ void tst_qqmllistreference::at()
tt.data.append(&tt);
tt.property.at = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.at(0) == 0);
+ QVERIFY(!ref.at(0));
}
}
@@ -484,27 +484,27 @@ void tst_qqmllistreference::clear()
{
QQmlListReference ref;
- QVERIFY(ref.clear() == false);
+ QVERIFY(!ref.clear());
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.clear() == false);
+ QVERIFY(!ref.clear());
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.clear() == true);
- QVERIFY(tt->data.count() == 0);
+ QVERIFY(ref.clear());
+ QCOMPARE(tt->data.count(), 0);
delete tt;
- QVERIFY(ref.clear() == false);
+ QVERIFY(!ref.clear());
}
{
TestType tt;
tt.property.clear = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.clear() == false);
+ QVERIFY(!ref.clear());
}
}
@@ -517,21 +517,21 @@ void tst_qqmllistreference::count()
{
QQmlListReference ref;
- QVERIFY(ref.count() == 0);
+ QCOMPARE(ref.count(), 0);
}
{
QQmlListReference ref(tt, "blah");
- QVERIFY(ref.count() == 0);
+ QCOMPARE(ref.count(), 0);
}
{
QQmlListReference ref(tt, "data");
- QVERIFY(ref.count() == 3);
+ QCOMPARE(ref.count(), 3);
tt->data.removeAt(1);
- QVERIFY(ref.count() == 2);
+ QCOMPARE(ref.count(), 2);
delete tt;
- QVERIFY(ref.count() == 0);
+ QCOMPARE(ref.count(), 0);
}
{
@@ -539,7 +539,7 @@ void tst_qqmllistreference::count()
tt.data.append(&tt);
tt.property.count = 0;
QQmlListReference ref(&tt, "data");
- QVERIFY(ref.count() == 0);
+ QCOMPARE(ref.count(), 0);
}
}
@@ -551,24 +551,24 @@ void tst_qqmllistreference::copy()
tt.data.append(&tt);
QQmlListReference *r1 = new QQmlListReference(&tt, "data");
- QVERIFY(r1->count() == 3);
+ QCOMPARE(r1->count(), 3);
QQmlListReference r2(*r1);
QQmlListReference r3;
r3 = *r1;
- QVERIFY(r2.count() == 3);
- QVERIFY(r3.count() == 3);
+ QCOMPARE(r2.count(), 3);
+ QCOMPARE(r3.count(), 3);
delete r1;
- QVERIFY(r2.count() == 3);
- QVERIFY(r3.count() == 3);
+ QCOMPARE(r2.count(), 3);
+ QCOMPARE(r3.count(), 3);
tt.data.removeAt(2);
- QVERIFY(r2.count() == 2);
- QVERIFY(r3.count() == 2);
+ QCOMPARE(r2.count(), 2);
+ QCOMPARE(r3.count(), 2);
}
void tst_qqmllistreference::qmlmetaproperty()
@@ -580,10 +580,10 @@ void tst_qqmllistreference::qmlmetaproperty()
QQmlProperty prop(&tt, QLatin1String("data"));
QVariant v = prop.read();
- QVERIFY(v.userType() == qMetaTypeId<QQmlListReference>());
+ QCOMPARE(v.userType(), qMetaTypeId<QQmlListReference>());
QQmlListReference ref = qvariant_cast<QQmlListReference>(v);
- QVERIFY(ref.count() == 3);
- QVERIFY(ref.listElementType() == &TestType::staticMetaObject);
+ QCOMPARE(ref.count(), 3);
+ QCOMPARE(ref.listElementType(), &TestType::staticMetaObject);
}
void tst_qqmllistreference::engineTypes()
@@ -595,14 +595,14 @@ void tst_qqmllistreference::engineTypes()
QVERIFY(o);
QQmlProperty p1(o, QLatin1String("myList"));
- QVERIFY(p1.propertyTypeCategory() == QQmlProperty::List);
+ QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::List);
QQmlProperty p2(o, QLatin1String("myList"), engine.rootContext());
- QVERIFY(p2.propertyTypeCategory() == QQmlProperty::List);
+ QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::List);
QVariant v = p2.read();
- QVERIFY(v.userType() == qMetaTypeId<QQmlListReference>());
+ QCOMPARE(v.userType(), qMetaTypeId<QQmlListReference>());
QQmlListReference ref = qvariant_cast<QQmlListReference>(v);
- QVERIFY(ref.count() == 2);
+ QCOMPARE(ref.count(), 2);
QVERIFY(ref.listElementType());
QVERIFY(ref.listElementType() != &QObject::staticMetaObject);
@@ -617,7 +617,7 @@ void tst_qqmllistreference::variantToList()
QObject *o = component.create();
QVERIFY(o);
- QVERIFY(o->property("value").userType() == qMetaTypeId<QQmlListReference>());
+ QCOMPARE(o->property("value").userType(), qMetaTypeId<QQmlListReference>());
QCOMPARE(o->property("test").toInt(), 1);
delete o;
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index 011db7b363..ba3f72f2c1 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -451,7 +451,7 @@ void tst_qqmllocale::firstDayOfWeek()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("firstDayOfWeek");
- QVERIFY(val.type() == QVariant::Int);
+ QCOMPARE(val.type(), QVariant::Int);
int day = int(QLocale(locale).firstDayOfWeek());
if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
@@ -486,12 +486,12 @@ void tst_qqmllocale::weekDays()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("weekDays");
- QVERIFY(val.userType() == qMetaTypeId<QJSValue>());
+ QCOMPARE(val.userType(), qMetaTypeId<QJSValue>());
QList<QVariant> qmlDays = val.toList();
QList<Qt::DayOfWeek> days = QLocale(locale).weekdays();
- QVERIFY(days.count() == qmlDays.count());
+ QCOMPARE(days.count(), qmlDays.count());
for (int i = 0; i < days.count(); ++i) {
int day = int(days.at(i));
@@ -528,12 +528,12 @@ void tst_qqmllocale::uiLanguages()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("uiLanguages");
- QVERIFY(val.userType() == qMetaTypeId<QJSValue>());
+ QCOMPARE(val.userType(), qMetaTypeId<QJSValue>());
QList<QVariant> qmlLangs = val.toList();
QStringList langs = QLocale(locale).uiLanguages();
- QVERIFY(langs.count() == qmlLangs.count());
+ QCOMPARE(langs.count(), qmlLangs.count());
for (int i = 0; i < langs.count(); ++i) {
QCOMPARE(langs.at(i), qmlLangs.at(i).toString());
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index f5423582b2..27e92f67a3 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -126,7 +126,7 @@ void tst_qqmlmetatype::initTestCase()
void tst_qqmlmetatype::qmlParserStatusCast()
{
- QVERIFY(QQmlMetaType::qmlType(QVariant::Int) == 0);
+ QVERIFY(!QQmlMetaType::qmlType(QVariant::Int));
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->parserStatusCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()) != 0);
@@ -146,7 +146,7 @@ void tst_qqmlmetatype::qmlParserStatusCast()
void tst_qqmlmetatype::qmlPropertyValueSourceCast()
{
- QVERIFY(QQmlMetaType::qmlType(QVariant::Int) == 0);
+ QVERIFY(!QQmlMetaType::qmlType(QVariant::Int));
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueSourceCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
@@ -166,7 +166,7 @@ void tst_qqmlmetatype::qmlPropertyValueSourceCast()
void tst_qqmlmetatype::qmlPropertyValueInterceptorCast()
{
- QVERIFY(QQmlMetaType::qmlType(QVariant::Int) == 0);
+ QVERIFY(!QQmlMetaType::qmlType(QVariant::Int));
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueInterceptorCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
@@ -224,8 +224,8 @@ void tst_qqmlmetatype::isList()
void tst_qqmlmetatype::defaultObject()
{
- QVERIFY(QQmlMetaType::defaultProperty(&QObject::staticMetaObject).name() == 0);
- QVERIFY(QQmlMetaType::defaultProperty(&ParserStatusTestType::staticMetaObject).name() == 0);
+ QVERIFY(!QQmlMetaType::defaultProperty(&QObject::staticMetaObject).name());
+ QVERIFY(!QQmlMetaType::defaultProperty(&ParserStatusTestType::staticMetaObject).name());
QCOMPARE(QString(QQmlMetaType::defaultProperty(&TestType::staticMetaObject).name()), QString("foo"));
QObject o;
@@ -233,8 +233,8 @@ void tst_qqmlmetatype::defaultObject()
ParserStatusTestType p;
QVERIFY(QQmlMetaType::defaultProperty((QObject *)0).name() == 0);
- QVERIFY(QQmlMetaType::defaultProperty(&o).name() == 0);
- QVERIFY(QQmlMetaType::defaultProperty(&p).name() == 0);
+ QVERIFY(!QQmlMetaType::defaultProperty(&o).name());
+ QVERIFY(!QQmlMetaType::defaultProperty(&p).name());
QCOMPARE(QString(QQmlMetaType::defaultProperty(&t).name()), QString("foo"));
}
@@ -270,8 +270,8 @@ void tst_qqmlmetatype::compositeType()
QQmlType *type = QQmlMetaType::qmlType(QString("ImplicitType"), QString(""), 1, 0);
QVERIFY(type);
- QVERIFY(type->module() == QLatin1String(""));
- QVERIFY(type->elementName() == QLatin1String("ImplicitType"));
+ QVERIFY(type->module().isEmpty());
+ QCOMPARE(type->elementName(), QLatin1String("ImplicitType"));
QCOMPARE(type->qmlTypeName(), QLatin1String("ImplicitType"));
QCOMPARE(type->sourceUrl(), testFileUrl("ImplicitType.qml"));
}
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/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
index 6866e74aa1..429f45b875 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.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
@@ -31,40 +31,39 @@
**
****************************************************************************/
-#ifndef QTQUICK2PLUGINPLUGIN_H
-#define QTQUICK2PLUGINPLUGIN_H
+#include <qtest.h>
+#include <private/qqmlopenmetaobject_p.h>
+#include <QtQml/qqmlengine.h>
-#include <QtCore/QPointer>
-#include <QtQml/private/qqmlinspectorinterface_p.h>
-
-namespace QmlJSDebugger {
-
-class AbstractViewInspector;
-
-namespace QtQuick2 {
-
-class QtQuick2Plugin : public QObject, public QQmlInspectorInterface
+class tst_qqmlopenmetaobject : public QObject
{
Q_OBJECT
- Q_DISABLE_COPY(QtQuick2Plugin)
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlInspectorInterface")
- Q_INTERFACES(QQmlInspectorInterface)
-
public:
- QtQuick2Plugin();
- ~QtQuick2Plugin();
+ tst_qqmlopenmetaobject() {}
- // QQmlInspectorInterface
- bool canHandleView(QObject *view);
- void activate(QObject *view);
- void deactivate();
- void clientMessage(const QByteArray &message);
+private slots:
+ void createProperties();
+};
-private:
- QPointer<AbstractViewInspector> m_inspector;
+class CustomObject: public QObject
+{
+ Q_OBJECT
+public:
+ CustomObject(QObject *parent = 0)
+ : QObject(parent) {}
};
-} // namespace QtQuick2
-} // namespace QmlJSDebugger
+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);
+}
+
+QTEST_MAIN(tst_qqmlopenmetaobject)
-#endif // QTQUICK2PLUGINPLUGIN_H
+#include "tst_qqmlopenmetaobject.moc"
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index a8b06ffa71..d6b1c86b88 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -159,10 +159,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());
@@ -188,12 +188,12 @@ void tst_qqmlproperty::qmlmetaproperty()
QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!prop.property().name());
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -255,7 +255,7 @@ void tst_qqmlproperty::registeredCompositeTypeProperty()
QQmlProperty p1e(obj, "first", &engine);
QQmlProperty p2e(obj, "second", &engine);
QQmlProperty p3e(obj, "third", &engine);
- QVERIFY(p1.propertyType() == p2.propertyType());
+ QCOMPARE(p1.propertyType(), p2.propertyType());
QVERIFY(p1.propertyType() != p3.propertyType());
// check that the values are retrievable from CPP
@@ -293,7 +293,7 @@ void tst_qqmlproperty::registeredCompositeTypeProperty()
QQmlProperty lp2e(obj, "sclistOne", &engine);
QQmlProperty lp3e(obj, "sclistTwo", &engine);
QVERIFY(lp1e.propertyType() != lp2e.propertyType());
- QVERIFY(lp2e.propertyType() == lp3e.propertyType());
+ QCOMPARE(lp2e.propertyType(), lp3e.propertyType());
// check that the list values are retrievable from CPP
QVariant firstList = obj->property("fclist");
@@ -408,10 +408,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;
@@ -439,12 +439,12 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!prop.property().name());
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -455,11 +455,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;
@@ -488,13 +488,13 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QCOMPARE(prop.propertyType(), (int)QVariant::Int);
QCOMPARE(prop.propertyTypeName(), "int");
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
- QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
- QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
+ QCOMPARE(QQmlPropertyPrivate::binding(prop), binding.data());
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -511,10 +511,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;
@@ -542,12 +542,12 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!prop.property().name());
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -558,11 +558,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;
@@ -591,13 +591,13 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(prop.propertyType(), (int)QVariant::Int);
QCOMPARE(prop.propertyTypeName(), "int");
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
- QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
- QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
+ QCOMPARE(QQmlPropertyPrivate::binding(prop), binding.data());
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -608,11 +608,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,13 +641,13 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
+ QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -657,11 +657,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,13 +690,13 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
+ QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -712,10 +712,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;
@@ -743,12 +743,12 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!prop.property().name());
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -759,11 +759,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;
@@ -792,13 +792,13 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QCOMPARE(prop.propertyType(), (int)QVariant::Int);
QCOMPARE(prop.propertyTypeName(), "int");
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
- QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
- QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
+ QCOMPARE(QQmlPropertyPrivate::binding(prop), binding.data());
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -815,10 +815,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;
@@ -846,12 +846,12 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!prop.property().name());
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -862,11 +862,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;
@@ -895,13 +895,13 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(prop.propertyType(), (int)QVariant::Int);
QCOMPARE(prop.propertyTypeName(), "int");
QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
- QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
- QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
- QVERIFY(binding != 0);
- QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding);
+ QCOMPARE(QQmlPropertyPrivate::binding(prop), binding.data());
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -912,11 +912,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,13 +945,13 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
+ QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -961,11 +961,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,13 +994,13 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QCOMPARE(prop.propertyType(), 0);
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);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!QQmlPropertyPrivate::binding(prop));
+ QQmlPropertyPrivate::setBinding(prop, binding.data());
+ QVERIFY(binding->ref == 1);
+ QVERIFY(!QQmlPropertyPrivate::signalExpression(prop));
+ QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(!sigExprWatcher.wasDeleted());
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
+ QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -1146,7 +1146,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());
@@ -1158,7 +1158,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());
@@ -1203,7 +1203,7 @@ void tst_qqmlproperty::read()
QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
QVariant v = p.read();
- QVERIFY(v.userType() == QMetaType::QObjectStar);
+ QCOMPARE(v.userType(), int(QMetaType::QObjectStar));
QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
}
{
@@ -1217,7 +1217,7 @@ void tst_qqmlproperty::read()
QVERIFY(p.propertyType() != QMetaType::QObjectStar);
QVariant v = p.read();
- QVERIFY(v.userType() == QMetaType::QObjectStar);
+ QCOMPARE(v.userType(), int(QMetaType::QObjectStar));
QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
}
@@ -1227,7 +1227,7 @@ void tst_qqmlproperty::read()
QVERIFY(object != 0);
QVariant v = QQmlProperty::read(object, "test", &engine);
- QVERIFY(v.userType() == QMetaType::QObjectStar);
+ QCOMPARE(v.userType(), int(QMetaType::QObjectStar));
QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
}
@@ -1337,7 +1337,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);
@@ -1351,7 +1351,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);
@@ -1643,7 +1643,7 @@ void tst_qqmlproperty::writeObjectToList()
MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
QVERIFY(container != 0);
QQmlListReference list(container, "children");
- QVERIFY(list.count() == 1);
+ QCOMPARE(list.count(), 1);
MyQmlObject *object = new MyQmlObject;
QQmlProperty prop(container, "children");
@@ -1659,7 +1659,7 @@ void tst_qqmlproperty::writeListToList()
MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
QVERIFY(container != 0);
QQmlListReference list(container, "children");
- QVERIFY(list.count() == 1);
+ QCOMPARE(list.count(), 1);
QList<QObject*> objList;
objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index ce2aab49c3..a5ae27d446 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -34,6 +34,7 @@
#include <qtest.h>
#include <private/qqmlpropertycache_p.h>
#include <QtQml/qqmlengine.h>
+#include <private/qv8engine_p.h>
#include "../../shared/util.h"
class tst_qqmlpropertycache : public QObject
@@ -102,10 +103,11 @@ QQmlPropertyData *cacheProperty(QQmlPropertyCache *cache, const char *name)
void tst_qqmlpropertycache::properties()
{
QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
DerivedObject object;
const QMetaObject *metaObject = object.metaObject();
- QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(&engine, metaObject));
+ QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
QVERIFY(data = cacheProperty(cache, "propertyA"));
@@ -124,10 +126,11 @@ void tst_qqmlpropertycache::properties()
void tst_qqmlpropertycache::propertiesDerived()
{
QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
DerivedObject object;
const QMetaObject *metaObject = object.metaObject();
- QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(&engine, &BaseObject::staticMetaObject));
+ QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(v4, &BaseObject::staticMetaObject));
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
@@ -147,10 +150,11 @@ void tst_qqmlpropertycache::propertiesDerived()
void tst_qqmlpropertycache::methods()
{
QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
DerivedObject object;
const QMetaObject *metaObject = object.metaObject();
- QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(&engine, metaObject));
+ QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
QVERIFY(data = cacheProperty(cache, "slotA"));
@@ -181,10 +185,11 @@ void tst_qqmlpropertycache::methods()
void tst_qqmlpropertycache::methodsDerived()
{
QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
DerivedObject object;
const QMetaObject *metaObject = object.metaObject();
- QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(&engine, &BaseObject::staticMetaObject));
+ QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(v4, &BaseObject::staticMetaObject));
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
@@ -216,10 +221,11 @@ void tst_qqmlpropertycache::methodsDerived()
void tst_qqmlpropertycache::signalHandlers()
{
QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
DerivedObject object;
const QMetaObject *metaObject = object.metaObject();
- QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(&engine, metaObject));
+ QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
QVERIFY(data = cacheProperty(cache, "onSignalA"));
@@ -244,10 +250,11 @@ void tst_qqmlpropertycache::signalHandlers()
void tst_qqmlpropertycache::signalHandlersDerived()
{
QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(&engine);
DerivedObject object;
const QMetaObject *metaObject = object.metaObject();
- QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(&engine, &BaseObject::staticMetaObject));
+ QQmlRefPointer<QQmlPropertyCache> parentCache(new QQmlPropertyCache(v4, &BaseObject::staticMetaObject));
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
index 4860602a45..2f3754e42d 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -104,7 +104,7 @@ void tst_QQmlPropertyMap::insert()
QQmlPropertyMap map;
map.insert(QLatin1String("key1"),100);
map.insert(QLatin1String("key2"),200);
- QVERIFY(map.keys().count() == 2);
+ QCOMPARE(map.keys().count(), 2);
QVERIFY(map.contains(QLatin1String("key1")));
QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
@@ -117,33 +117,33 @@ void tst_QQmlPropertyMap::insert()
//QQmlPropertyMap has an invokable keys() method
QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"keys\" is not permitted, conflicts with internal symbols.");
map.insert(QLatin1String("keys"), 1);
- QVERIFY(map.keys().count() == 2);
+ QCOMPARE(map.keys().count(), 2);
QVERIFY(!map.contains(QLatin1String("keys")));
QVERIFY(map.value(QLatin1String("keys")).isNull());
//QQmlPropertyMap has a deleteLater() slot
QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"deleteLater\" is not permitted, conflicts with internal symbols.");
map.insert(QLatin1String("deleteLater"), 1);
- QVERIFY(map.keys().count() == 2);
+ QCOMPARE(map.keys().count(), 2);
QVERIFY(!map.contains(QLatin1String("deleteLater")));
QVERIFY(map.value(QLatin1String("deleteLater")).isNull());
//QQmlPropertyMap has an valueChanged() signal
QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"valueChanged\" is not permitted, conflicts with internal symbols.");
map.insert(QLatin1String("valueChanged"), 1);
- QVERIFY(map.keys().count() == 2);
+ QCOMPARE(map.keys().count(), 2);
QVERIFY(!map.contains(QLatin1String("valueChanged")));
QVERIFY(map.value(QLatin1String("valueChanged")).isNull());
//but 'valueChange' should be ok
map.insert(QLatin1String("valueChange"), 1);
- QVERIFY(map.keys().count() == 3);
+ QCOMPARE(map.keys().count(), 3);
QVERIFY(map.contains(QLatin1String("valueChange")));
QCOMPARE(map.value(QLatin1String("valueChange")), QVariant(1));
//'valueCHANGED' should be ok, too
map.insert(QLatin1String("valueCHANGED"), 1);
- QVERIFY(map.keys().count() == 4);
+ QCOMPARE(map.keys().count(), 4);
QVERIFY(map.contains(QLatin1String("valueCHANGED")));
QCOMPARE(map.value(QLatin1String("valueCHANGED")), QVariant(1));
}
@@ -153,7 +153,7 @@ void tst_QQmlPropertyMap::operatorInsert()
QQmlPropertyMap map;
map[QLatin1String("key1")] = 100;
map[QLatin1String("key2")] = 200;
- QVERIFY(map.keys().count() == 2);
+ QCOMPARE(map.keys().count(), 2);
QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
QCOMPARE(map.value(QLatin1String("key2")), QVariant(200));
@@ -167,7 +167,7 @@ void tst_QQmlPropertyMap::operatorValue()
QQmlPropertyMap map;
map.insert(QLatin1String("key1"),100);
map.insert(QLatin1String("key2"),200);
- QVERIFY(map.count() == 2);
+ QCOMPARE(map.count(), 2);
QVERIFY(map.contains(QLatin1String("key1")));
const QQmlPropertyMap &constMap = map;
@@ -182,12 +182,12 @@ void tst_QQmlPropertyMap::clear()
{
QQmlPropertyMap map;
map.insert(QLatin1String("key1"),100);
- QVERIFY(map.keys().count() == 1);
+ QCOMPARE(map.keys().count(), 1);
QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
map.clear(QLatin1String("key1"));
- QVERIFY(map.keys().count() == 1);
+ QCOMPARE(map.keys().count(), 1);
QVERIFY(map.contains(QLatin1String("key1")));
QCOMPARE(map.value(QLatin1String("key1")), QVariant());
}
@@ -463,7 +463,7 @@ void tst_QQmlPropertyMap::QTBUG_35906()
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QVariant value = obj->property("testValue");
- QVERIFY(value.type() == QVariant::Int);
+ QCOMPARE(value.type(), QVariant::Int);
QCOMPARE(value.toInt(), 42);
}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 671f7b5e73..b5bdc3a3b9 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -651,7 +651,7 @@ void tst_qqmlqt::createQmlObject()
QQuickItem *item = qobject_cast<QQuickItem *>(object);
QVERIFY(item != 0);
- QVERIFY(item->childItems().count() == 1);
+ QCOMPARE(item->childItems().count(), 1);
delete object;
}
diff --git a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
index 17083a4c6a..5a98a6bed8 100644
--- a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
+++ b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
@@ -134,7 +134,7 @@ void tst_qqmltimer::notRepeating()
QCOMPARE(helper.count, 1);
consistentWait(200);
QCOMPARE(helper.count, 1);
- QVERIFY(timer->isRunning() == false);
+ QVERIFY(!timer->isRunning());
}
void tst_qqmltimer::notRepeatingStart()
@@ -157,7 +157,7 @@ void tst_qqmltimer::notRepeatingStart()
QCOMPARE(helper.count, 1);
consistentWait(200);
QCOMPARE(helper.count, 1);
- QVERIFY(timer->isRunning() == false);
+ QVERIFY(!timer->isRunning());
delete timer;
}
@@ -186,8 +186,8 @@ void tst_qqmltimer::repeat()
timer->stop();
consistentWait(200);
- QVERIFY(helper.count == oldCount);
- QVERIFY(timer->isRunning() == false);
+ QCOMPARE(helper.count, oldCount);
+ QVERIFY(!timer->isRunning());
QSignalSpy spy(timer, SIGNAL(repeatChanged()));
@@ -221,7 +221,7 @@ void tst_qqmltimer::triggeredOnStart()
QCOMPARE(helper.count, 2);
consistentWait(200);
QCOMPARE(helper.count, 2);
- QVERIFY(timer->isRunning() == false);
+ QVERIFY(!timer->isRunning());
QSignalSpy spy(timer, SIGNAL(triggeredOnStartChanged()));
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 578004b0a1..52f744578a 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -1183,7 +1183,7 @@ void tst_qqmlvaluetypes::enums()
QQmlComponent component(&engine, testFileUrl("enums.1.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->font().capitalization() == QFont::AllUppercase);
+ QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
delete object;
}
@@ -1191,7 +1191,7 @@ void tst_qqmlvaluetypes::enums()
QQmlComponent component(&engine, testFileUrl("enums.2.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->font().capitalization() == QFont::AllUppercase);
+ QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
delete object;
}
@@ -1199,7 +1199,7 @@ void tst_qqmlvaluetypes::enums()
QQmlComponent component(&engine, testFileUrl("enums.3.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->font().capitalization() == QFont::AllUppercase);
+ QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
delete object;
}
@@ -1207,7 +1207,7 @@ void tst_qqmlvaluetypes::enums()
QQmlComponent component(&engine, testFileUrl("enums.4.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->font().capitalization() == QFont::AllUppercase);
+ QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
delete object;
}
@@ -1215,7 +1215,7 @@ void tst_qqmlvaluetypes::enums()
QQmlComponent component(&engine, testFileUrl("enums.5.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->font().capitalization() == QFont::AllUppercase);
+ QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
delete object;
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
new file mode 100644
index 0000000000..f0dc8ed3fd
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
@@ -0,0 +1,14 @@
+PROPFIND /container/ HTTP/1.1
+Depth: 1
+Content-Length: 95
+Connection: Keep-Alive
+Accept-Encoding: gzip, deflate
+Accept-Language: en-US,*
+Content-type:i application/xml; charset="utf-8"
+User-Agent: Mozilla/5.0
+Host: {{ServerHostUrl}}
+
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:">
+<D:allprop/>
+</D:propfind>
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.reply.body b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.reply.body
new file mode 100644
index 0000000000..ef0c38956c
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.reply.body
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+<D:multistatus xmlns:D="DAV:">
+ <D:response>
+ <D:href>/container/</D:href>
+ <D:propstat>
+ <D:prop xmlns:R="http://ns.example.com/boxschema/">
+ <R:bigbox><R:BoxType>Box type A</R:BoxType></R:bigbox>
+ <R:author><R:Name>Hadrian</R:Name></R:author>
+ <D:creationdate>1997-12-01T17:42:21-08:00</D:creationdate>
+ <D:displayname>Example collection</D:displayname>
+ <D:resourcetype><D:collection/></D:resourcetype>
+ <D:supportedlock>
+ <D:lockentry>
+ <D:lockscope><D:exclusive/></D:lockscope>
+ <D:locktype><D:write/></D:locktype>
+ </D:lockentry>
+ <D:lockentry>
+ <D:lockscope><D:shared/></D:lockscope>
+ <D:locktype><D:write/></D:locktype>
+ </D:lockentry>
+ </D:supportedlock>
+ </D:prop>
+ <D:status>HTTP/1.1 200 OK</D:status>
+ </D:propstat>
+ </D:response>
+/D:multistatus>
+-->
+<D:multistatus xmlns:D="DAV:"><D:response><D:href>/container/</D:href><D:propstat><D:prop xmlns:R="http://ns.example.com/boxschema/"><R:bigbox><R:BoxType>Box type A</R:BoxType></R:bigbox><R:author><R:Name>Hadrian</R:Name></R:author><D:creationdate>1997-12-01T17:42:21-08:00</D:creationdate><D:displayname>Example collection</D:displayname><D:resourcetype><D:collection/></D:resourcetype><D:supportedlock><D:lockentry><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry><D:lockentry><D:lockscope><D:shared/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry></D:supportedlock></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
new file mode 100644
index 0000000000..2d14de634d
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
@@ -0,0 +1,18 @@
+PROPFIND /file HTTP/1.1
+Content-Length: 192
+Connection: Keep-Alive
+Accept-Encoding: gzip, deflate
+Accept-Language: en-US,*
+Content-type: text/xml; charset="utf-8"
+User-Agent: Mozilla/5.0
+Host: {{ServerHostUrl}}
+
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:">
+<D:prop xmlns:R="http://www.foo.bar/boxschema/">
+<R:bigbox/>
+<R:author/>
+<R:DingALing/>
+<R:Random/>
+</D:prop>
+</D:propfind>
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.body b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.body
new file mode 100644
index 0000000000..9e5028fe01
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.body
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+<D:multistatus xmlns:D="DAV:">
+ <D:response xmlns:R="http://ns.example.com/boxschema/">
+ <D:href>http://www.example.com/file</D:href>
+ <D:propstat>
+ <D:prop>
+ <R:bigbox>
+ <R:BoxType>Box type A</R:BoxType>
+ </R:bigbox>
+ <R:author>
+ <R:Name>J.J. Johnson</R:Name>
+ </R:author>
+ </D:prop>
+ <D:status>HTTP/1.1 200 OK</D:status>
+ </D:propstat>
+ <D:propstat>
+ <D:prop>
+ <R:DingALing/>
+ <R:Random/>
+ </D:prop>
+ <D:status>HTTP/1.1 403 Forbidden</D:status>
+ <D:responsedescription>The user does not have access to the DingALing property.</D:responsedescription>
+ </D:propstat>
+ </D:response>
+ <D:responsedescription>There has been an access violation error.</D:responsedescription>
+</D:multistatus>
+-->
+<D:multistatus xmlns:D="DAV:"><D:response xmlns:R="http://ns.example.com/boxschema/"><D:href>http://www.example.com/file</D:href><D:propstat><D:prop><R:bigbox><R:BoxType>Box type A</R:BoxType></R:bigbox><R:author><R:Name>J.J. Johnson</R:Name></R:author></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat><D:propstat><D:prop><R:DingALing/><R:Random/></D:prop><D:status>HTTP/1.1 403 Forbidden</D:status><D:responsedescription>The user does not have access to the DingALing property.</D:responsedescription></D:propstat></D:response><D:responsedescription>There has been an access violation error.</D:responsedescription></D:multistatus>
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.header b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.header
new file mode 100644
index 0000000000..50fa080ad2
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.reply.header
@@ -0,0 +1,2 @@
+HTTP/1.1 207 Multi-Status
+Content-Type: text/xml; charset="utf-8"
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
new file mode 100644
index 0000000000..2f47a5e62c
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+QtObject {
+ property string url
+ property bool xmlTest: false
+ property bool typeTest: false
+
+ function checkXML(document)
+ {
+ if (document.xmlVersion != "1.0")
+ return;
+
+ if (document.xmlEncoding != "utf-8")
+ return;
+
+ if (document.documentElement == null)
+ return;
+
+ var multistatus = document.documentElement;
+ if (multistatus.nodeName != "multistatus")
+ return;
+
+ if (multistatus.namespaceUri != "DAV:")
+ return;
+
+ var multistatusChildTags = [ "response" ];
+ for (var node = 0; node < multistatus.childNodes.length; ++node) {
+ if (multistatus.childNodes[node].nodeName != multistatusChildTags[node])
+ return;
+ }
+
+ var response = multistatus.childNodes[0];
+ var responseChildTags = [ "href", "propstat" ];
+ for (var node = 0; node < response.childNodes.length; ++node) {
+ var nodeName = response.childNodes[node].nodeName;
+ if (nodeName != responseChildTags[node])
+ return;
+
+ var nodeValue = response.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "href") && (nodeValue != "/container/"))
+ return;
+ }
+
+ var propstat = response.childNodes[1];
+ var propstatChildTags = ["prop", "status"];
+ for (var node = 0; node < propstat.childNodes.length; ++node) {
+ var nodeName = propstat.childNodes[node].nodeName;
+ if (nodeName != propstatChildTags[node])
+ return;
+
+ var nodeValue = propstat.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "status") && (nodeValue != "HTTP/1.1 200 OK"))
+ return;
+ }
+
+ var prop = propstat.childNodes[0];
+ var propChildTags = [ "bigbox", "author", "creationdate", "displayname", "resourcetype", "supportedlock" ];
+ for (var node = 0; node < prop.childNodes.length; ++node) {
+ var nodeName = prop.childNodes[node].nodeName;
+ if (nodeName != propChildTags[node])
+ return;
+
+ if (nodeName == "bigbox") {
+ if (prop.childNodes[node].childNodes.length != 1)
+ return;
+
+ var boxType = prop.childNodes[node].childNodes[0];
+ if (boxType.nodeName != "BoxType")
+ return;
+ if (boxType.childNodes[0].nodeValue != "Box type A")
+ return;
+ }
+
+ if (nodeName == "author") {
+ if (prop.childNodes[node].childNodes.length != 1)
+ return;
+
+ var boxType = prop.childNodes[node].childNodes[0];
+ if (boxType.nodeName != "Name")
+ return;
+ if (boxType.childNodes[0].nodeValue != "Hadrian")
+ return;
+ }
+
+ if (nodeName == "creationdate") {
+ if (prop.childNodes[node].childNodes.length != 1)
+ return;
+
+ if (prop.childNodes[node].childNodes[0].nodeValue != "1997-12-01T17:42:21-08:00")
+ return;
+ }
+
+ if (nodeName == "displayname") {
+ if (prop.childNodes[node].childNodes.length != 1)
+ return;
+
+ if (prop.childNodes[node].childNodes[0].nodeValue != "Example collection")
+ return;
+ }
+
+ if (nodeName == "resourcetpye") {
+ if (prop.childNodes[node].childNodes.length != 1)
+ return;
+
+ if (prop.childNodes[node].childNodes[0].nodeValue != "collection")
+ return;
+ }
+
+ if (nodeName == "supportedlock") {
+ if (prop.childNodes[node].childNodes.length != 2)
+ return;
+
+ var lockEntry1 = prop.childNodes[node].childNodes[0];
+ if (lockEntry1.nodeName != "lockentry")
+ return;
+ if (lockEntry1.childNodes.length != 2)
+ return;
+ if (lockEntry1.childNodes[0].nodeName != "lockscope")
+ return;
+ if (lockEntry1.childNodes[0].childNodes[0].nodeName != "exclusive")
+ return;
+ if (lockEntry1.childNodes[1].nodeName != "locktype")
+ return;
+ if (lockEntry1.childNodes[1].childNodes[0].nodeName != "write")
+ return;
+
+ var lockEntry2 = prop.childNodes[node].childNodes[1];
+ if (lockEntry2.nodeName != "lockentry")
+ return;
+ if (lockEntry2.childNodes.length != 2)
+ return;
+ if (lockEntry2.childNodes[0].nodeName != "lockscope")
+ return;
+ if (lockEntry2.childNodes[0].childNodes[0].nodeName != "shared")
+ return;
+ if (lockEntry2.childNodes[1].nodeName != "locktype")
+ return;
+ if (lockEntry2.childNodes[1].childNodes[0].nodeName != "write")
+ return;
+ }
+ }
+
+ xmlTest = true;
+ }
+
+ Component.onCompleted: {
+
+ var request = new XMLHttpRequest();
+ request.open("PROPFIND", url);
+ request.responseType = "document";
+ request.setRequestHeader("Depth", "1");
+
+ request.onreadystatechange = function() {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ checkXML(request.response);
+ typeTest = (request.responseType == "document");
+ }
+ }
+
+ var requestBody = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
+ "<D:propfind xmlns:D=\"DAV:\">\n" +
+ "<D:allprop/>\n" +
+ "</D:propfind>\n"
+ request.send(requestBody);
+ }
+}
+
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
new file mode 100644
index 0000000000..01353e5e95
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+QtObject {
+ property string url
+ property bool xmlTest: false
+ property bool typeTest: false
+
+ function checkXML(document)
+ {
+ if (document.xmlVersion != "1.0")
+ return;
+
+ if (document.xmlEncoding != "utf-8")
+ return;
+
+ if (document.documentElement == null)
+ return;
+
+ var multistatus = document.documentElement;
+ if (multistatus.nodeName != "multistatus")
+ return;
+
+ if (multistatus.namespaceUri != "DAV:")
+ return;
+
+ var multistatusChildTags = [ "response", "responsedescription" ];
+ for (var node = 0; node < multistatus.childNodes.length; ++node) {
+ if (multistatus.childNodes[node].nodeName != multistatusChildTags[node])
+ return;
+ }
+
+ var response = multistatus.childNodes[0];
+ var responseChildTags = [ "href", "propstat", "propstat" ];
+ for (var node = 0; node < response.childNodes.length; ++node) {
+ var nodeName = response.childNodes[node].nodeName;
+ if (nodeName != responseChildTags[node])
+ return;
+
+ var nodeValue = response.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "href") && (nodeValue != "http://www.example.com/file"))
+ return;
+ }
+
+ if (multistatus.childNodes[1].childNodes[0].nodeValue != "There has been an access violation error.")
+ return;
+
+ var propstat1 = response.childNodes[1];
+ var propstat1ChildTags = ["prop", "status"];
+ for (var node = 0; node < propstat1.childNodes.length; ++node) {
+ var nodeName = propstat1.childNodes[node].nodeName;
+ if (nodeName != propstat1ChildTags[node])
+ return;
+
+ var nodeValue = propstat1.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "status") && (nodeValue != "HTTP/1.1 200 OK"))
+ return;
+ }
+
+ var prop1 = propstat1.childNodes[0];
+ var prop1ChildTags = [ "bigbox", "author" ];
+ for (var node = 0; node < prop1.childNodes.length; ++node) {
+ var nodeName = prop1.childNodes[node].nodeName;
+ if (nodeName != prop1ChildTags[node])
+ return;
+
+ if (nodeName == "bigbox") {
+ if (prop1.childNodes[node].childNodes.length != 1)
+ return;
+
+ var boxType = prop1.childNodes[node].childNodes[0];
+ if (boxType.nodeName != "BoxType")
+ return;
+ if (boxType.childNodes[0].nodeValue != "Box type A")
+ return;
+ }
+ }
+
+ var propstat2 = response.childNodes[2];
+ var propstat2ChildTags = ["prop", "status", "responsedescription" ];
+ for (var node = 0; node < propstat2.childNodes.length; ++node) {
+ var nodeName = propstat2.childNodes[node].nodeName;
+ if (nodeName != propstat2ChildTags[node])
+ return;
+
+ var nodeValue = propstat2.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "status") && (nodeValue != "HTTP/1.1 403 Forbidden"))
+ return;
+ if ((nodeName == "responsedescription") && (nodeValue != "The user does not have access to the DingALing property."))
+ return;
+ }
+
+ var prop2 = propstat2.childNodes[0];
+ var prop2ChildTags = [ "DingALing", "Random" ];
+ for (var node = 0; node < prop2.childNodes.length; ++node) {
+ var nodeName = prop2.childNodes[node].nodeName;
+ if (nodeName != prop2ChildTags[node])
+ return;
+ }
+
+ xmlTest = true;
+ }
+
+ Component.onCompleted: {
+
+ var request = new XMLHttpRequest();
+ request.open("PROPFIND", url);
+ request.responseType = "document";
+
+ request.onreadystatechange = function() {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ checkXML(request.response);
+ typeTest = (request.responseType == "document");
+ }
+ }
+
+ var requestBody = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
+ "<D:propfind xmlns:D=\"DAV:\">\n" +
+ "<D:prop xmlns:R=\"http://www.foo.bar/boxschema/\">\n" +
+ "<R:bigbox/>\n" +
+ "<R:author/>\n" +
+ "<R:DingALing/>\n" +
+ "<R:Random/>\n" +
+ "</D:prop>\n" +
+ "</D:propfind>\n"
+ request.send(requestBody);
+ }
+}
+
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
new file mode 100644
index 0000000000..3b4d1e2c1e
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+QtObject {
+ property string url
+ property bool xmlTest: false
+ property bool typeTest: false
+
+ function checkXML(document)
+ {
+ if (document.xmlVersion != "1.0")
+ return;
+
+ if (document.xmlEncoding != "utf-8")
+ return;
+
+ if (document.documentElement == null)
+ return;
+
+ var multistatus = document.documentElement;
+ if (multistatus.nodeName != "multistatus")
+ return;
+
+ if (multistatus.namespaceUri != "DAV:")
+ return;
+
+ var multistatusChildTags = [ "response", "responsedescription" ];
+ for (var node = 0; node < multistatus.childNodes.length; ++node) {
+ if (multistatus.childNodes[node].nodeName != multistatusChildTags[node])
+ return;
+ }
+
+ var response = multistatus.childNodes[0];
+ var responseChildTags = [ "href", "propstat", "propstat" ];
+ for (var node = 0; node < response.childNodes.length; ++node) {
+ var nodeName = response.childNodes[node].nodeName;
+ if (nodeName != responseChildTags[node])
+ return;
+
+ var nodeValue = response.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "href") && (nodeValue != "http://www.example.com/file"))
+ return;
+ }
+
+ if (multistatus.childNodes[1].childNodes[0].nodeValue != "There has been an access violation error.")
+ return;
+
+ var propstat1 = response.childNodes[1];
+ var propstat1ChildTags = ["prop", "status"];
+ for (var node = 0; node < propstat1.childNodes.length; ++node) {
+ var nodeName = propstat1.childNodes[node].nodeName;
+ if (nodeName != propstat1ChildTags[node])
+ return;
+
+ var nodeValue = propstat1.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "status") && (nodeValue != "HTTP/1.1 200 OK"))
+ return;
+ }
+
+ var prop1 = propstat1.childNodes[0];
+ var prop1ChildTags = [ "bigbox", "author" ];
+ for (var node = 0; node < prop1.childNodes.length; ++node) {
+ var nodeName = prop1.childNodes[node].nodeName;
+ if (nodeName != prop1ChildTags[node])
+ return;
+
+ if (nodeName == "bigbox") {
+ if (prop1.childNodes[node].childNodes.length != 1)
+ return;
+
+ var boxType = prop1.childNodes[node].childNodes[0];
+ if (boxType.nodeName != "BoxType")
+ return;
+ if (boxType.childNodes[0].nodeValue != "Box type A")
+ return;
+ }
+ }
+
+ var propstat2 = response.childNodes[2];
+ var propstat2ChildTags = ["prop", "status", "responsedescription" ];
+ for (var node = 0; node < propstat2.childNodes.length; ++node) {
+ var nodeName = propstat2.childNodes[node].nodeName;
+ if (nodeName != propstat2ChildTags[node])
+ return;
+
+ var nodeValue = propstat2.childNodes[node].childNodes[0].nodeValue;
+ if ((nodeName == "status") && (nodeValue != "HTTP/1.1 403 Forbidden"))
+ return;
+ if ((nodeName == "responsedescription") && (nodeValue != "The user does not have access to the DingALing property."))
+ return;
+ }
+
+ var prop2 = propstat2.childNodes[0];
+ var prop2ChildTags = [ "DingALing", "Random" ];
+ for (var node = 0; node < prop2.childNodes.length; ++node) {
+ var nodeName = prop2.childNodes[node].nodeName;
+ if (nodeName != prop2ChildTags[node])
+ return;
+ }
+
+ xmlTest = true;
+ }
+
+ Component.onCompleted: {
+
+ var request = new XMLHttpRequest();
+ request.open("PROPFIND", url);
+
+ request.onreadystatechange = function() {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ checkXML(request.responseXML);
+ typeTest = (request.responseType == "document");
+ }
+ }
+
+ var requestBody = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
+ "<D:propfind xmlns:D=\"DAV:\">\n" +
+ "<D:prop xmlns:R=\"http://www.foo.bar/boxschema/\">\n" +
+ "<R:bigbox/>\n" +
+ "<R:author/>\n" +
+ "<R:DingALing/>\n" +
+ "<R:Random/>\n" +
+ "</D:prop>\n" +
+ "</D:propfind>\n"
+ request.send(requestBody);
+ }
+}
+
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..ae0350278a 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();
@@ -100,6 +101,10 @@ private slots:
void nonUtf8();
void nonUtf8_data();
+ // WebDAV
+ void sendPropfind();
+ void sendPropfind_data();
+
// Attributes
void document();
void element();
@@ -172,7 +177,7 @@ void tst_qqmlxmlhttprequest::callbackException()
object->setProperty("which", which);
component.completeCreate();
- QTRY_VERIFY(object->property("threw").toBool() == true);
+ QTRY_VERIFY(object->property("threw").toBool());
}
// Test that the state value properties on the XMLHttpRequest constructor have the correct values.
@@ -258,7 +263,7 @@ void tst_qqmlxmlhttprequest::open()
QCOMPARE(object->property("responseText").toBool(), true);
QCOMPARE(object->property("responseXML").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
void tst_qqmlxmlhttprequest::open_data()
@@ -371,7 +376,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader()
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
// Test valid setRequestHeader() calls with different header cases
@@ -389,7 +394,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader_caseInsensitive()
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
// Test setting headers before open() throws exception
void tst_qqmlxmlhttprequest::setRequestHeader_unsent()
@@ -454,7 +459,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName()
QCOMPARE(object->property("responseText").toBool(), true);
QCOMPARE(object->property("responseXML").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
// Test that attempting to set a header after a request is sent throws an exception
@@ -474,7 +479,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader_sent()
QCOMPARE(object->property("test").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
// Invalid arg count throws exception
@@ -505,7 +510,7 @@ void tst_qqmlxmlhttprequest::send_alreadySent()
QVERIFY(!object.isNull());
QCOMPARE(object->property("test").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
// Test that sends for GET, HEAD and DELETE ignore data
@@ -525,7 +530,7 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
{
@@ -542,7 +547,7 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
{
@@ -559,7 +564,7 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
}
@@ -581,7 +586,7 @@ void tst_qqmlxmlhttprequest::send_withdata()
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
void tst_qqmlxmlhttprequest::send_withdata_data()
@@ -655,7 +660,7 @@ void tst_qqmlxmlhttprequest::abort_unsent()
QCOMPARE(object->property("responseText").toBool(), true);
QCOMPARE(object->property("responseXML").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
// Test abort() cancels an open (but unsent) request
@@ -674,7 +679,7 @@ void tst_qqmlxmlhttprequest::abort_opened()
QCOMPARE(object->property("responseText").toBool(), true);
QCOMPARE(object->property("responseXML").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
// Test abort() aborts in progress send
@@ -700,7 +705,7 @@ void tst_qqmlxmlhttprequest::abort()
QCOMPARE(object->property("didNotSeeUnsent").toBool(), true);
QCOMPARE(object->property("endStateUnsent").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
}
void tst_qqmlxmlhttprequest::getResponseHeader()
@@ -725,7 +730,7 @@ void tst_qqmlxmlhttprequest::getResponseHeader()
QCOMPARE(object->property("readyState").toBool(), true);
QCOMPARE(object->property("openedState").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("headersReceivedState").toBool(), true);
QCOMPARE(object->property("headersReceivedNullHeader").toBool(), true);
@@ -767,7 +772,7 @@ void tst_qqmlxmlhttprequest::getResponseHeader_args()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("exceptionThrown").toBool() == true);
+ QTRY_VERIFY(object->property("exceptionThrown").toBool());
}
void tst_qqmlxmlhttprequest::getAllResponseHeaders()
@@ -791,7 +796,7 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders()
QCOMPARE(object->property("readyState").toBool(), true);
QCOMPARE(object->property("openedState").toBool(), true);
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("headersReceivedState").toBool(), true);
QCOMPARE(object->property("headersReceivedHeader").toBool(), true);
@@ -827,7 +832,7 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders_args()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("exceptionThrown").toBool() == true);
+ QTRY_VERIFY(object->property("exceptionThrown").toBool());
}
void tst_qqmlxmlhttprequest::getBinaryData()
@@ -845,7 +850,25 @@ void tst_qqmlxmlhttprequest::getBinaryData()
component.completeCreate();
QFileInfo fileInfo("data/qml_logo.png");
- QTRY_VERIFY(object->property("readSize").toInt() == fileInfo.size());
+ QTRY_COMPARE(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()
@@ -866,7 +889,7 @@ void tst_qqmlxmlhttprequest::status()
object->setProperty("expectedStatus", status);
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("unsentException").toBool(), true);
QCOMPARE(object->property("openedException").toBool(), true);
@@ -905,7 +928,7 @@ void tst_qqmlxmlhttprequest::statusText()
object->setProperty("expectedStatus", statusText);
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("unsentException").toBool(), true);
QCOMPARE(object->property("openedException").toBool(), true);
@@ -945,7 +968,7 @@ void tst_qqmlxmlhttprequest::responseText()
object->setProperty("expectedText", responseText);
component.completeCreate();
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("unsent").toBool(), true);
QCOMPARE(object->property("opened").toBool(), true);
@@ -981,7 +1004,7 @@ void tst_qqmlxmlhttprequest::nonUtf8()
object->setProperty("fileName", fileName);
QMetaObject::invokeMethod(object.data(), "startRequest");
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("responseText").toString(), responseText);
@@ -1007,6 +1030,46 @@ void tst_qqmlxmlhttprequest::nonUtf8_data()
QTest::newRow("responseXML") << "utf16.xml" << "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone='yes'?>\n<root>\n" + uc + "\n</root>\n" << QString('\n' + uc + '\n');
}
+void tst_qqmlxmlhttprequest::sendPropfind()
+{
+ const QString prefix = "WebDAV//";
+
+ QFETCH(QString, qml);
+ QFETCH(QString, resource);
+ QFETCH(QString, expectedFile);
+ QFETCH(QString, replyHeader);
+ QFETCH(QString, replyBody);
+
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+
+ QVERIFY(server.wait(testFileUrl(prefix + expectedFile),
+ testFileUrl(prefix + replyHeader),
+ testFileUrl(prefix + replyBody)));
+
+ QQmlComponent component(&engine, testFileUrl(prefix + qml));
+ QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString(resource));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("xmlTest").toBool());
+ QCOMPARE(object->property("typeTest").toBool(), true);
+}
+
+void tst_qqmlxmlhttprequest::sendPropfind_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("resource");
+ QTest::addColumn<QString>("expectedFile");
+ QTest::addColumn<QString>("replyHeader");
+ QTest::addColumn<QString>("replyBody");
+
+ QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). Get response with responseXML.") << "sendPropfind.responseXML.qml" << "/file" << "propfind.file.expect" << "propfind.file.reply.header" << "propfind.file.reply.body";
+ QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). Get response with response.") << "sendPropfind.response.qml" << "/file" << "propfind.file.expect" << "propfind.file.reply.header" << "propfind.file.reply.body";
+ QTest::newRow("Send PROPFIND \"allprop\" request for collection.") << "sendPropfind.collection.allprop.qml" << "/container/" << "propfind.collection.allprop.expect" << "propfind.file.reply.header" << "propfind.collection.allprop.reply.body";
+}
+
// Test that calling hte XMLHttpRequest methods on a non-XMLHttpRequest object
// throws an exception
void tst_qqmlxmlhttprequest::invalidMethodUsage()
@@ -1045,7 +1108,7 @@ void tst_qqmlxmlhttprequest::redirects()
object->setProperty("expectedText", "");
component.completeCreate();
- QTRY_VERIFY(object->property("done").toBool() == true);
+ QTRY_VERIFY(object->property("done").toBool());
QCOMPARE(object->property("dataOK").toBool(), true);
}
@@ -1062,7 +1125,7 @@ void tst_qqmlxmlhttprequest::redirects()
object->setProperty("expectedText", "");
component.completeCreate();
- QTRY_VERIFY(object->property("done").toBool() == true);
+ QTRY_VERIFY(object->property("done").toBool());
QCOMPARE(object->property("dataOK").toBool(), true);
}
@@ -1083,7 +1146,7 @@ void tst_qqmlxmlhttprequest::redirects()
if (object->property("done").toBool()) break;
QTest::qWait(50);
}
- QVERIFY(object->property("done").toBool() == true);
+ QVERIFY(object->property("done").toBool());
QCOMPARE(object->property("dataOK").toBool(), true);
}
@@ -1095,7 +1158,7 @@ void tst_qqmlxmlhttprequest::responseXML_invalid()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("xmlNull").toBool(), true);
}
@@ -1107,7 +1170,7 @@ void tst_qqmlxmlhttprequest::document()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("xmlTest").toBool(), true);
}
@@ -1119,7 +1182,7 @@ void tst_qqmlxmlhttprequest::element()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("xmlTest").toBool(), true);
}
@@ -1131,7 +1194,7 @@ void tst_qqmlxmlhttprequest::attr()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("xmlTest").toBool(), true);
}
@@ -1143,9 +1206,10 @@ void tst_qqmlxmlhttprequest::text()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("xmlTest").toBool(), true);
+ QCOMPARE(object->property("status").toInt(), 200);
}
// Test the CDataSection DOM element
@@ -1155,9 +1219,10 @@ void tst_qqmlxmlhttprequest::cdata()
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_VERIFY(object->property("dataOK").toBool() == true);
+ QTRY_VERIFY(object->property("dataOK").toBool());
QCOMPARE(object->property("xmlTest").toBool(), true);
+ QCOMPARE(object->property("status").toInt(), 200);
}
void tst_qqmlxmlhttprequest::stateChangeCallingContext()
@@ -1179,7 +1244,7 @@ void tst_qqmlxmlhttprequest::stateChangeCallingContext()
object->setProperty("serverBaseUrl", server.baseUrl().toString());
component.completeCreate();
server.sendDelayedItem();
- QTRY_VERIFY(object->property("success").toBool() == true);
+ QTRY_VERIFY(object->property("success").toBool());
}
QTEST_MAIN(tst_qqmlxmlhttprequest)
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index 59be469d5b..dc6e2fa561 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -295,11 +295,11 @@ void tst_qquickfolderlistmodel::changeDrive()
flm->setProperty("folder",QUrl::fromLocalFile(dataDir));
QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(dataDir));
- QTRY_VERIFY(folderChangeSpy.count() == 1);
+ QTRY_COMPARE(folderChangeSpy.count(), 1);
flm->setProperty("folder",QUrl::fromLocalFile("X:/resetfiltering/"));
QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile("X:/resetfiltering/"));
- QTRY_VERIFY(folderChangeSpy.count() == 2);
+ QTRY_COMPARE(folderChangeSpy.count(), 2);
}
#endif
diff --git a/tests/auto/qml/qv4debugger/qv4debugger.pro b/tests/auto/qml/qv4debugger/qv4debugger.pro
index 2a318955f3..540cab70e6 100644
--- a/tests/auto/qml/qv4debugger/qv4debugger.pro
+++ b/tests/auto/qml/qv4debugger/qv4debugger.pro
@@ -2,6 +2,14 @@ CONFIG += testcase
TARGET = tst_qv4debugger
macx:CONFIG -= app_bundle
-SOURCES += tst_qv4debugger.cpp
+SOURCES += \
+ $$PWD/tst_qv4debugger.cpp \
+ $$PWD/../../../../src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+
+HEADERS += \
+ $$PWD/../../../../src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+
+INCLUDEPATH += \
+ $$PWD/../../../../src/plugins/qmltooling/qmldbg_debugger
QT += core-private gui-private qml-private network testlib
diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
index 056b24d167..7772d16234 100644
--- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
@@ -32,12 +32,15 @@
****************************************************************************/
#include <QtTest/QtTest>
+#include "qv4datacollector.h"
+
#include <QJSEngine>
#include <QQmlEngine>
#include <QQmlComponent>
#include <private/qv4engine_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv8engine_p.h>
+#include <private/qv4objectiterator_p.h>
using namespace QV4;
using namespace QV4::Debugging;
@@ -85,99 +88,93 @@ 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:
void evaluateFinished();
};
-
-namespace {
-class TestCollector: public QV4::Debugging::Debugger::Collector
+class TestAgent : public QObject
{
+ Q_OBJECT
public:
- TestCollector(QV4::ExecutionEngine *engine)
- : Collector(engine)
- , destination(0)
- {}
-
- virtual ~TestCollector() {}
-
- void setDestination(QVariantMap *dest)
- { destination = dest; }
-
-protected:
- virtual void addUndefined(const QString &name)
- {
- destination->insert(name, QStringLiteral("undefined")); // TODO: add a user-defined type for this
- }
-
- virtual void addNull(const QString &name)
- {
- destination->insert(name, QStringLiteral("null")); // TODO: add a user-defined type for this
- }
-
- virtual void addBoolean(const QString &name, bool value)
- {
- destination->insert(name, value);
- }
+ typedef QV4DataCollector::Refs Refs;
+ typedef QV4DataCollector::Ref Ref;
+ struct NamedRefs {
+ NamedRefs(QV4DataCollector *collector = 0): collector(collector) {}
+
+ QStringList names;
+ Refs refs;
+ QV4DataCollector *collector;
+
+ int size() const {
+ Q_ASSERT(names.size() == refs.size());
+ return names.size();
+ }
- virtual void addString(const QString &name, const QString &value)
- {
- destination->insert(name, value);
- }
+ bool contains(const QString &name) const {
+ return names.contains(name);
+ }
- virtual void addObject(const QString &name, const QV4::Value &value)
- {
- QV4::Scope scope(engine());
- QV4::ScopedObject obj(scope, value.asObject());
+#define DUMP_JSON(x) {\
+ QJsonDocument doc(x);\
+ qDebug() << #x << "=" << doc.toJson(QJsonDocument::Indented);\
+}
- QVariantMap props, *prev = &props;
- qSwap(destination, prev);
- collect(obj);
- qSwap(destination, prev);
+ QJsonObject rawValue(const QString &name) const {
+ Q_ASSERT(contains(name));
+ return collector->lookupRef(refs.at(names.indexOf(name)));
+ }
- destination->insert(name, props);
- }
+ QJsonValue value(const QString &name) const {
+ return rawValue(name).value(QStringLiteral("value"));
+ }
- virtual void addInteger(const QString &name, int value)
- {
- destination->insert(name, QVariant::fromValue<double>(static_cast<double>(value)));
- }
+ QString type(const QString &name) const {
+ return rawValue(name).value(QStringLiteral("type")).toString();
+ }
- virtual void addDouble(const QString &name, double value)
- {
- destination->insert(name, QVariant::fromValue<double>(value));
- }
+ void dump(const QString &name) const {
+ if (!contains(name)) {
+ qDebug() << "no" << name;
+ return;
+ }
-private:
- QVariantMap *destination;
-};
-}
+ QJsonObject o = collector->lookupRef(refs.at(names.indexOf(name)));
+ QJsonDocument d;
+ d.setObject(o);
+ qDebug() << name << "=" << d.toJson(QJsonDocument::Indented);
+ }
+ };
-class TestAgent : public QV4::Debugging::DebuggerAgent
-{
- Q_OBJECT
-public:
- TestAgent()
+ TestAgent(QV4::ExecutionEngine *engine)
: m_wasPaused(false)
, m_captureContextInfo(false)
+ , m_thrownValue(-1)
+ , collector(engine)
+ , m_debugger(0)
{
}
- virtual void debuggerPaused(Debugger *debugger, PauseReason reason)
+public slots:
+ void debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason)
{
- Q_ASSERT(m_debuggers.count() == 1 && m_debuggers.first() == debugger);
+ Q_ASSERT(debugger == m_debugger);
+ Q_ASSERT(debugger->engine() == collector.engine());
m_wasPaused = true;
m_pauseReason = reason;
m_statesWhenPaused << debugger->currentExecutionState();
- TestCollector collector(debugger->engine());
- QVariantMap tmp;
- collector.setDestination(&tmp);
- debugger->collectThrownValue(&collector);
- m_thrownValue = tmp["exception"];
+ if (debugger->state() == QV4::Debugging::Debugger::Paused &&
+ debugger->engine()->hasException) {
+ Refs refs;
+ RefHolder holder(&collector, &refs);
+ ExceptionCollectJob job(debugger->engine(), &collector);
+ debugger->runInEngine(&job);
+ Q_ASSERT(refs.size() > 0);
+ m_thrownValue = refs.first();
+ }
foreach (const TestBreakPoint &bp, m_breakPointsToAddWhenPaused)
debugger->addBreakPoint(bp.fileName, bp.lineNumber);
@@ -186,11 +183,13 @@ public:
m_stackTrace = debugger->stackTrace();
while (!m_expressionRequests.isEmpty()) {
+ Q_ASSERT(debugger->state() == QV4::Debugging::Debugger::Paused);
ExpressionRequest request = m_expressionRequests.takeFirst();
- QVariantMap result;
- collector.setDestination(&result);
- debugger->evaluateExpression(request.frameNr, request.expression, &collector);
- m_expressionResults << result[QString::fromLatin1("body")];
+ m_expressionResults << Refs();
+ RefHolder holder(&collector, &m_expressionResults.last());
+ ExpressionEvalJob job(debugger->engine(), request.frameNr, request.expression,
+ &collector);
+ debugger->runInEngine(&job);
}
if (m_captureContextInfo)
@@ -199,15 +198,7 @@ public:
debugger->resume(Debugger::FullThrottle);
}
- virtual void sourcesCollected(Debugger *debugger, QStringList sources, int requestSequenceNr)
- {
- Q_UNUSED(debugger);
- Q_UNUSED(sources);
- Q_UNUSED(requestSequenceNr);
- }
-
- int debuggerCount() const { return m_debuggers.count(); }
-
+public:
struct TestBreakPoint
{
TestBreakPoint() : lineNumber(-1) {}
@@ -219,37 +210,49 @@ public:
void captureContextInfo(Debugger *debugger)
{
- TestCollector collector(debugger->engine());
-
for (int i = 0, ei = m_stackTrace.size(); i != ei; ++i) {
- QVariantMap args;
- collector.setDestination(&args);
- debugger->collectArgumentsInContext(&collector, i);
- m_capturedArguments.append(args);
-
- QVariantMap locals;
- collector.setDestination(&locals);
- debugger->collectLocalsInContext(&collector, i);
- m_capturedLocals.append(locals);
+ m_capturedArguments.append(NamedRefs(&collector));
+ RefHolder argHolder(&collector, &m_capturedArguments.last().refs);
+ ArgumentCollectJob argumentsJob(debugger->engine(), &collector,
+ &m_capturedArguments.last().names, i, 0);
+ debugger->runInEngine(&argumentsJob);
+
+ m_capturedLocals.append(NamedRefs(&collector));
+ RefHolder localHolder(&collector, &m_capturedLocals.last().refs);
+ LocalCollectJob localsJob(debugger->engine(), &collector,
+ &m_capturedLocals.last().names, i, 0);
+ debugger->runInEngine(&localsJob);
}
}
+ void addDebugger(QV4::Debugging::Debugger *debugger)
+ {
+ Q_ASSERT(!m_debugger);
+ m_debugger = debugger;
+ connect(m_debugger,
+ SIGNAL(debuggerPaused(QV4::Debugging::Debugger*,QV4::Debugging::PauseReason)),
+ this,
+ SLOT(debuggerPaused(QV4::Debugging::Debugger*,QV4::Debugging::PauseReason)));
+ }
+
bool m_wasPaused;
PauseReason m_pauseReason;
bool m_captureContextInfo;
QList<Debugger::ExecutionState> m_statesWhenPaused;
QList<TestBreakPoint> m_breakPointsToAddWhenPaused;
QVector<QV4::StackFrame> m_stackTrace;
- QList<QVariantMap> m_capturedArguments;
- QList<QVariantMap> m_capturedLocals;
- QVariant m_thrownValue;
+ QVector<NamedRefs> m_capturedArguments;
+ QVector<NamedRefs> m_capturedLocals;
+ qint64 m_thrownValue;
+ QV4DataCollector collector;
struct ExpressionRequest {
QString expression;
int frameNr;
};
QVector<ExpressionRequest> m_expressionRequests;
- QVector<QVariant> m_expressionResults;
+ QVector<Refs> m_expressionResults;
+ QV4::Debugging::Debugger *m_debugger;
// Utility methods:
void dumpStackTrace() const
@@ -315,7 +318,7 @@ void tst_qv4debugger::init()
m_v4->enableDebugger();
m_engine->moveToThread(m_javaScriptThread);
m_javaScriptThread->start();
- m_debuggerAgent = new TestAgent;
+ m_debuggerAgent = new TestAgent(m_v4);
m_debuggerAgent->addDebugger(m_v4->debugger);
}
@@ -327,7 +330,6 @@ void tst_qv4debugger::cleanup()
delete m_javaScriptThread;
m_engine = 0;
m_v4 = 0;
- QCOMPARE(m_debuggerAgent->debuggerCount(), 0);
delete m_debuggerAgent;
m_debuggerAgent = 0;
}
@@ -338,7 +340,7 @@ void tst_qv4debugger::breakAnywhere()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- m_debuggerAgent->pauseAll();
+ m_v4->debugger->pause();
evaluateJavaScript(script, "testFile");
QVERIFY(m_debuggerAgent->m_wasPaused);
}
@@ -349,7 +351,7 @@ void tst_qv4debugger::pendingBreakpoint()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- m_debuggerAgent->addBreakPoint("testfile", 2);
+ m_v4->debugger->addBreakPoint("testfile", 2);
evaluateJavaScript(script, "testfile");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 1);
@@ -365,7 +367,7 @@ void tst_qv4debugger::liveBreakPoint()
"var j = i + 1\n"
"var k = i\n";
m_debuggerAgent->m_breakPointsToAddWhenPaused << TestAgent::TestBreakPoint("liveBreakPoint", 3);
- m_debuggerAgent->pauseAll();
+ m_v4->debugger->pause();
evaluateJavaScript(script, "liveBreakPoint");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 2);
@@ -380,8 +382,8 @@ void tst_qv4debugger::removePendingBreakPoint()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- int id = m_debuggerAgent->addBreakPoint("removePendingBreakPoint", 2);
- m_debuggerAgent->removeBreakPoint(id);
+ m_v4->debugger->addBreakPoint("removePendingBreakPoint", 2);
+ m_v4->debugger->removeBreakPoint("removePendingBreakPoint", 2);
evaluateJavaScript(script, "removePendingBreakPoint");
QVERIFY(!m_debuggerAgent->m_wasPaused);
}
@@ -392,7 +394,7 @@ void tst_qv4debugger::addBreakPointWhilePaused()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- m_debuggerAgent->addBreakPoint("addBreakPointWhilePaused", 1);
+ m_v4->debugger->addBreakPoint("addBreakPointWhilePaused", 1);
m_debuggerAgent->m_breakPointsToAddWhenPaused << TestAgent::TestBreakPoint("addBreakPointWhilePaused", 2);
evaluateJavaScript(script, "addBreakPointWhilePaused");
QVERIFY(m_debuggerAgent->m_wasPaused);
@@ -422,7 +424,7 @@ void tst_qv4debugger::removeBreakPointForNextInstruction()
QMetaObject::invokeMethod(m_engine, "injectFunction", Qt::BlockingQueuedConnection,
Q_ARG(QString, "someCall"), Q_ARG(InjectedFunction, someCall));
- m_debuggerAgent->addBreakPoint("removeBreakPointForNextInstruction", 2);
+ m_v4->debugger->addBreakPoint("removeBreakPointForNextInstruction", 2);
evaluateJavaScript(script, "removeBreakPointForNextInstruction");
QVERIFY(!m_debuggerAgent->m_wasPaused);
@@ -439,16 +441,19 @@ void tst_qv4debugger::conditionalBreakPoint()
"}\n"
"test()\n";
- m_debuggerAgent->addBreakPoint("conditionalBreakPoint", 3, /*enabled*/true, QStringLiteral("i > 10"));
+ m_v4->debugger->addBreakPoint("conditionalBreakPoint", 3, QStringLiteral("i > 10"));
evaluateJavaScript(script, "conditionalBreakPoint");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 4);
QV4::Debugging::Debugger::ExecutionState state = m_debuggerAgent->m_statesWhenPaused.first();
QCOMPARE(state.fileName, QString("conditionalBreakPoint"));
QCOMPARE(state.lineNumber, 3);
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0].size(), 2);
- QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains(QStringLiteral("i")));
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["i"].toInt(), 11);
+
+ QVERIFY(m_debuggerAgent->m_capturedLocals.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedLocals.at(0);
+ QCOMPARE(frame0.size(), 2);
+ QVERIFY(frame0.contains("i"));
+ QCOMPARE(frame0.value("i").toInt(), 11);
}
void tst_qv4debugger::conditionalBreakPointInQml()
@@ -459,7 +464,7 @@ void tst_qv4debugger::conditionalBreakPointInQml()
QScopedPointer<QThread> debugThread(new QThread);
debugThread->start();
- QScopedPointer<TestAgent> debuggerAgent(new TestAgent);
+ QScopedPointer<TestAgent> debuggerAgent(new TestAgent(v4));
debuggerAgent->addDebugger(v4->debugger);
debuggerAgent->moveToThread(debugThread.data());
@@ -474,7 +479,7 @@ void tst_qv4debugger::conditionalBreakPointInQml()
" }\n"
"}\n", QUrl("test.qml"));
- debuggerAgent->addBreakPoint("test.qml", 7, /*enabled*/true, "root.foo == 42");
+ v4->debugger->addBreakPoint("test.qml", 7, "root.foo == 42");
QScopedPointer<QObject> obj(component.create());
QCOMPARE(obj->property("success").toBool(), true);
@@ -496,16 +501,18 @@ void tst_qv4debugger::readArguments()
"}\n"
"var four;\n"
"f(1, 'two', null, four);\n";
- m_debuggerAgent->addBreakPoint("readArguments", 2);
+ m_v4->debugger->addBreakPoint("readArguments", 2);
evaluateJavaScript(script, "readArguments");
QVERIFY(m_debuggerAgent->m_wasPaused);
- QCOMPARE(m_debuggerAgent->m_capturedArguments[0].size(), 4);
- QVERIFY(m_debuggerAgent->m_capturedArguments[0].contains(QStringLiteral("a")));
- QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["a"].type(), QVariant::Double);
- QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["a"].toDouble(), 1.0);
- QVERIFY(m_debuggerAgent->m_capturedArguments[0].contains("b"));
- QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["b"].type(), QVariant::String);
- QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["b"].toString(), QLatin1String("two"));
+ QVERIFY(m_debuggerAgent->m_capturedArguments.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedArguments.at(0);
+ QCOMPARE(frame0.size(), 4);
+ QVERIFY(frame0.contains(QStringLiteral("a")));
+ QCOMPARE(frame0.type(QStringLiteral("a")), QStringLiteral("number"));
+ QCOMPARE(frame0.value(QStringLiteral("a")).toDouble(), 1.0);
+ QVERIFY(frame0.names.contains("b"));
+ QCOMPARE(frame0.type(QStringLiteral("b")), QStringLiteral("string"));
+ QCOMPARE(frame0.value(QStringLiteral("b")).toString(), QStringLiteral("two"));
}
void tst_qv4debugger::readLocals()
@@ -518,15 +525,17 @@ void tst_qv4debugger::readLocals()
" return c === d\n"
"}\n"
"f(1, 2, 3);\n";
- m_debuggerAgent->addBreakPoint("readLocals", 3);
+ m_v4->debugger->addBreakPoint("readLocals", 3);
evaluateJavaScript(script, "readLocals");
QVERIFY(m_debuggerAgent->m_wasPaused);
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0].size(), 2);
- QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains("c"));
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["c"].type(), QVariant::Double);
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["c"].toDouble(), 3.0);
- QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains("d"));
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["d"].toString(), QString("undefined"));
+ QVERIFY(m_debuggerAgent->m_capturedLocals.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedLocals.at(0);
+ QCOMPARE(frame0.size(), 2);
+ QVERIFY(frame0.contains("c"));
+ QCOMPARE(frame0.type("c"), QStringLiteral("number"));
+ QCOMPARE(frame0.value("c").toDouble(), 3.0);
+ QVERIFY(frame0.contains("d"));
+ QCOMPARE(frame0.type("d"), QStringLiteral("undefined"));
}
void tst_qv4debugger::readObject()
@@ -538,26 +547,43 @@ void tst_qv4debugger::readObject()
" return b\n"
"}\n"
"f({head: 1, tail: { head: 'asdf', tail: null }});\n";
- m_debuggerAgent->addBreakPoint("readObject", 3);
+ m_v4->debugger->addBreakPoint("readObject", 3);
evaluateJavaScript(script, "readObject");
QVERIFY(m_debuggerAgent->m_wasPaused);
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0].size(), 1);
- QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains("b"));
- QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["b"].type(), QVariant::Map);
-
- QVariantMap b = m_debuggerAgent->m_capturedLocals[0]["b"].toMap();
- QCOMPARE(b.size(), 2);
- QVERIFY(b.contains("head"));
- QCOMPARE(b["head"].type(), QVariant::Double);
- QCOMPARE(b["head"].toDouble(), 1.0);
- QVERIFY(b.contains("tail"));
- QCOMPARE(b["tail"].type(), QVariant::Map);
-
- QVariantMap b_tail = b["tail"].toMap();
- QCOMPARE(b_tail.size(), 2);
- QVERIFY(b_tail.contains("head"));
- QCOMPARE(b_tail["head"].type(), QVariant::String);
- QCOMPARE(b_tail["head"].toString(), QString("asdf"));
+ QVERIFY(m_debuggerAgent->m_capturedLocals.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedLocals.at(0);
+ QCOMPARE(frame0.size(), 1);
+ QVERIFY(frame0.contains("b"));
+ QCOMPARE(frame0.type("b"), QStringLiteral("object"));
+ QJsonObject b = frame0.rawValue("b");
+ QVERIFY(b.contains(QStringLiteral("properties")));
+ QVERIFY(b.value("properties").isArray());
+ QJsonArray b_props = b.value("properties").toArray();
+ QCOMPARE(b_props.size(), 2);
+
+ QVERIFY(b_props.at(0).isObject());
+ QJsonObject b_head = b_props.at(0).toObject();
+ QCOMPARE(b_head.value("name").toString(), QStringLiteral("head"));
+ QCOMPARE(b_head.value("type").toString(), QStringLiteral("number"));
+ QCOMPARE(b_head.value("value").toDouble(), 1.0);
+ QVERIFY(b_props.at(1).isObject());
+ QJsonObject b_tail = b_props.at(1).toObject();
+ QCOMPARE(b_tail.value("name").toString(), QStringLiteral("tail"));
+ QVERIFY(b_tail.contains("ref"));
+
+ QJsonObject b_tail_value = frame0.collector->lookupRef(b_tail.value("ref").toInt());
+ QCOMPARE(b_tail_value.value("type").toString(), QStringLiteral("object"));
+ QVERIFY(b_tail_value.contains("properties"));
+ QJsonArray b_tail_props = b_tail_value.value("properties").toArray();
+ QCOMPARE(b_tail_props.size(), 2);
+ QJsonObject b_tail_head = b_tail_props.at(0).toObject();
+ QCOMPARE(b_tail_head.value("name").toString(), QStringLiteral("head"));
+ QCOMPARE(b_tail_head.value("type").toString(), QStringLiteral("string"));
+ QCOMPARE(b_tail_head.value("value").toString(), QStringLiteral("asdf"));
+ QJsonObject b_tail_tail = b_tail_props.at(1).toObject();
+ QCOMPARE(b_tail_tail.value("name").toString(), QStringLiteral("tail"));
+ QCOMPARE(b_tail_tail.value("type").toString(), QStringLiteral("null"));
+ QVERIFY(b_tail_tail.value("value").isNull());
}
void tst_qv4debugger::readContextInAllFrames()
@@ -573,7 +599,7 @@ void tst_qv4debugger::readContextInAllFrames()
" return 1;\n" // breakpoint
"}\n"
"fact(12);\n";
- m_debuggerAgent->addBreakPoint("readFormalsInAllFrames", 7);
+ m_v4->debugger->addBreakPoint("readFormalsInAllFrames", 7);
evaluateJavaScript(script, "readFormalsInAllFrames");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_stackTrace.size(), 13);
@@ -581,18 +607,20 @@ void tst_qv4debugger::readContextInAllFrames()
QCOMPARE(m_debuggerAgent->m_capturedLocals.size(), 13);
for (int i = 0; i < 12; ++i) {
- QCOMPARE(m_debuggerAgent->m_capturedArguments[i].size(), 1);
- QVERIFY(m_debuggerAgent->m_capturedArguments[i].contains("n"));
- QCOMPARE(m_debuggerAgent->m_capturedArguments[i]["n"].type(), QVariant::Double);
- QCOMPARE(m_debuggerAgent->m_capturedArguments[i]["n"].toDouble(), i + 1.0);
-
- QCOMPARE(m_debuggerAgent->m_capturedLocals[i].size(), 1);
- QVERIFY(m_debuggerAgent->m_capturedLocals[i].contains("n_1"));
+ const TestAgent::NamedRefs &args = m_debuggerAgent->m_capturedArguments.at(i);
+ QCOMPARE(args.size(), 1);
+ QVERIFY(args.contains("n"));
+ QCOMPARE(args.type("n"), QStringLiteral("number"));
+ QCOMPARE(args.value("n").toDouble(), i + 1.0);
+
+ const TestAgent::NamedRefs &locals = m_debuggerAgent->m_capturedLocals.at(i);
+ QCOMPARE(locals.size(), 1);
+ QVERIFY(locals.contains("n_1"));
if (i == 0) {
- QCOMPARE(m_debuggerAgent->m_capturedLocals[i]["n_1"].toString(), QString("undefined"));
+ QCOMPARE(locals.type("n_1"), QStringLiteral("undefined"));
} else {
- QCOMPARE(m_debuggerAgent->m_capturedLocals[i]["n_1"].type(), QVariant::Double);
- QCOMPARE(m_debuggerAgent->m_capturedLocals[i]["n_1"].toInt(), i);
+ QCOMPARE(locals.type("n_1"), QStringLiteral("number"));
+ QCOMPARE(locals.value("n_1").toInt(), i);
}
}
QCOMPARE(m_debuggerAgent->m_capturedArguments[12].size(), 0);
@@ -606,13 +634,16 @@ void tst_qv4debugger::pauseOnThrow()
" throw n\n"
"}\n"
"die('hard');\n";
- m_debuggerAgent->setBreakOnThrow(true);
+ m_v4->debugger->setBreakOnThrow(true);
evaluateJavaScript(script, "pauseOnThrow");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_pauseReason, Throwing);
QCOMPARE(m_debuggerAgent->m_stackTrace.size(), 2);
- QCOMPARE(m_debuggerAgent->m_thrownValue.type(), QVariant::String);
- QCOMPARE(m_debuggerAgent->m_thrownValue.toString(), QString("hard"));
+ QVERIFY(m_debuggerAgent->m_thrownValue >= qint64(0));
+ QJsonObject exception = m_debuggerAgent->collector.lookupRef(m_debuggerAgent->m_thrownValue);
+// DUMP_JSON(exception);
+ QCOMPARE(exception.value("type").toString(), QStringLiteral("string"));
+ QCOMPARE(exception.value("value").toString(), QStringLiteral("hard"));
}
void tst_qv4debugger::breakInCatch()
@@ -624,7 +655,7 @@ void tst_qv4debugger::breakInCatch()
" console.log(e, 'me');\n"
"}\n";
- m_debuggerAgent->addBreakPoint("breakInCatch", 4);
+ m_v4->debugger->addBreakPoint("breakInCatch", 4);
evaluateJavaScript(script, "breakInCatch");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_pauseReason, BreakPoint);
@@ -641,7 +672,7 @@ void tst_qv4debugger::breakInWith()
" console.log('give the answer');\n"
"}\n";
- m_debuggerAgent->addBreakPoint("breakInWith", 2);
+ m_v4->debugger->addBreakPoint("breakInWith", 2);
evaluateJavaScript(script, "breakInWith");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_pauseReason, BreakPoint);
@@ -669,13 +700,21 @@ void tst_qv4debugger::evaluateExpression()
request.frameNr = 1;
m_debuggerAgent->m_expressionRequests << request;
- m_debuggerAgent->addBreakPoint("evaluateExpression", 3);
+ m_v4->debugger->addBreakPoint("evaluateExpression", 3);
evaluateJavaScript(script, "evaluateExpression");
QCOMPARE(m_debuggerAgent->m_expressionResults.count(), 2);
- QCOMPARE(m_debuggerAgent->m_expressionResults[0].toInt(), 10);
- QCOMPARE(m_debuggerAgent->m_expressionResults[1].toInt(), 20);
+ QCOMPARE(m_debuggerAgent->m_expressionResults[0].size(), 1);
+ QJsonObject result0 =
+ m_debuggerAgent->collector.lookupRef(m_debuggerAgent->m_expressionResults[0].first());
+ QCOMPARE(result0.value("type").toString(), QStringLiteral("number"));
+ QCOMPARE(result0.value("value").toInt(), 10);
+ QCOMPARE(m_debuggerAgent->m_expressionResults[1].size(), 1);
+ QJsonObject result1 =
+ m_debuggerAgent->collector.lookupRef(m_debuggerAgent->m_expressionResults[1].first());
+ QCOMPARE(result1.value("type").toString(), QStringLiteral("number"));
+ QCOMPARE(result1.value("value").toInt(), 20);
}
QTEST_MAIN(tst_qv4debugger)
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/plugins/qmltooling/shared/qmlinspectorconstants.h b/tests/auto/qmltest/selftests/tst_grabImage.qml
index d76e172844..7a758ae8fc 100644
--- a/src/plugins/qmltooling/shared/qmlinspectorconstants.h
+++ 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,36 +31,28 @@
**
****************************************************************************/
-#ifndef QMLINSPECTORCONSTANTS_H
-#define QMLINSPECTORCONSTANTS_H
-
-#include <QtQml/private/qqmlglobal_p.h>
-
-namespace QmlJSDebugger {
-namespace Constants {
-
-enum DesignTool {
- NoTool = 0,
- SelectionToolMode = 1,
- MarqueeSelectionToolMode = 2,
- MoveToolMode = 3,
- ResizeToolMode = 4,
- ZoomMode = 6
-};
-
-static const int PressAndHoldTimeout = 800;
-
-static const double ZoomSnapDelta = 0.04;
-
-static const int EditorItemDataKey = 1000;
-
-enum GraphicsItemTypes {
- EditorItemType = 0xEAAA,
- ResizeHandleItemType = 0xEAEA
-};
-
-
-} // namespace Constants
-} // namespace QmlJSDebugger
-
-#endif // QMLINSPECTORCONSTANTS_H
+import QtQuick 2.0
+import QtTest 1.1
+
+TestCase {
+ id: testCase
+ name: "tst_grabImage"
+ when: windowShown
+
+ 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/qmltest/window/tst_clickwindow.qml b/tests/auto/qmltest/window/tst_clickwindow.qml
new file mode 100644
index 0000000000..bbe091990c
--- /dev/null
+++ b/tests/auto/qmltest/window/tst_clickwindow.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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.0
+import QtQuick.Window 2.0
+import QtTest 1.1
+
+Item {
+ width: height
+ height: 40
+ MouseArea {
+ id: ma
+ anchors.fill: parent
+
+ property bool everClicked: false
+
+ onClicked: everClicked = true;
+ }
+
+ Window {
+ id: ma2Window
+ width: height
+ height: 40
+ MouseArea {
+ id: ma2
+ anchors.fill: parent
+
+ property bool everClicked: false
+
+ onClicked: everClicked = true;
+ }
+
+ Component.onCompleted: ma2Window.show();
+ }
+
+ TestCase {
+ name: "ClickWindow"
+ when: windowShown
+
+ function test_clickBothWindows() {
+ mouseClick(ma, 20, 20);
+ verify(ma.everClicked);
+ mouseClick(ma2, 20, 20);
+ verify(ma2.everClicked);
+ }
+ }
+}
diff --git a/tests/auto/quick/geometry/tst_geometry.cpp b/tests/auto/quick/geometry/tst_geometry.cpp
index 1cc9b112cc..bdd6f1a394 100644
--- a/tests/auto/quick/geometry/tst_geometry.cpp
+++ b/tests/auto/quick/geometry/tst_geometry.cpp
@@ -58,7 +58,7 @@ void GeometryTest::testPoint2D()
QCOMPARE(geometry.sizeOfVertex(), (int) sizeof(float) * 2);
QCOMPARE(geometry.vertexCount(), 4);
QCOMPARE(geometry.indexCount(), 0);
- QVERIFY(geometry.indexData() == 0);
+ QVERIFY(!geometry.indexData());
QSGGeometry::updateRectGeometry(&geometry, QRectF(1, 2, 3, 4));
@@ -91,7 +91,7 @@ void GeometryTest::testTexturedPoint2D()
QCOMPARE(geometry.sizeOfVertex(), (int) sizeof(float) * 4);
QCOMPARE(geometry.vertexCount(), 4);
QCOMPARE(geometry.indexCount(), 0);
- QVERIFY(geometry.indexData() == 0);
+ QVERIFY(!geometry.indexData());
QSGGeometry::updateTexturedRectGeometry(&geometry, QRectF(1, 2, 3, 4), QRectF(5, 6, 7, 8));
@@ -163,7 +163,7 @@ void GeometryTest::testCustomGeometry()
for (int i=0; i<4000; ++i)
QCOMPARE(ii[i], (quint16) i);
for (int i=0; i<1000; ++i)
- QVERIFY(v[i].v1 == 6);
+ QCOMPARE(v[i].v1, float(6));
}
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/qquickanchors/tst_qquickanchors.cpp b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
index 6591d84504..597ea87feb 100644
--- a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
+++ b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
@@ -405,15 +405,15 @@ void tst_qquickanchors::resetConvenience()
//fill
itemPrivate->anchors()->setFill(baseItem);
- QVERIFY(itemPrivate->anchors()->fill() == baseItem);
+ QCOMPARE(itemPrivate->anchors()->fill(), baseItem);
itemPrivate->anchors()->resetFill();
- QVERIFY(itemPrivate->anchors()->fill() == 0);
+ QVERIFY(!itemPrivate->anchors()->fill());
//centerIn
itemPrivate->anchors()->setCenterIn(baseItem);
- QVERIFY(itemPrivate->anchors()->centerIn() == baseItem);
+ QCOMPARE(itemPrivate->anchors()->centerIn(), baseItem);
itemPrivate->anchors()->resetCenterIn();
- QVERIFY(itemPrivate->anchors()->centerIn() == 0);
+ QVERIFY(!itemPrivate->anchors()->centerIn());
delete item;
delete baseItem;
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index a0accfcd58..45694f38dd 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -335,48 +335,48 @@ void tst_qquickanimatedimage::sourceSizeChanges()
// Local
ctxt->setContextProperty("srcImage", QUrl(""));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
- QTRY_VERIFY(sourceSizeSpy.count() == 0);
+ QTRY_COMPARE(sourceSizeSpy.count(), 0);
ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 1);
+ QTRY_COMPARE(sourceSizeSpy.count(), 1);
ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 1);
+ QTRY_COMPARE(sourceSizeSpy.count(), 1);
ctxt->setContextProperty("srcImage", testFileUrl("hearts_copy.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 1);
+ QTRY_COMPARE(sourceSizeSpy.count(), 1);
ctxt->setContextProperty("srcImage", testFileUrl("colors.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 2);
+ QTRY_COMPARE(sourceSizeSpy.count(), 2);
ctxt->setContextProperty("srcImage", QUrl(""));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
- QTRY_VERIFY(sourceSizeSpy.count() == 3);
+ QTRY_COMPARE(sourceSizeSpy.count(), 3);
// Remote
ctxt->setContextProperty("srcImage", server.url("/hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 4);
+ QTRY_COMPARE(sourceSizeSpy.count(), 4);
ctxt->setContextProperty("srcImage", server.url("/hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 4);
+ QTRY_COMPARE(sourceSizeSpy.count(), 4);
ctxt->setContextProperty("srcImage", server.url("/hearts_copy.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 4);
+ QTRY_COMPARE(sourceSizeSpy.count(), 4);
ctxt->setContextProperty("srcImage", server.url("/colors.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
- QTRY_VERIFY(sourceSizeSpy.count() == 5);
+ QTRY_COMPARE(sourceSizeSpy.count(), 5);
ctxt->setContextProperty("srcImage", QUrl(""));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
- QTRY_VERIFY(sourceSizeSpy.count() == 6);
+ QTRY_COMPARE(sourceSizeSpy.count(), 6);
delete anim;
}
@@ -397,8 +397,8 @@ void tst_qquickanimatedimage::qtbug_16520()
QVERIFY(anim != 0);
anim->setProperty("source", server.urlString("/stickman.gif"));
- QTRY_VERIFY(anim->opacity() == 0);
- QTRY_VERIFY(anim->opacity() == 1);
+ QTRY_COMPARE(anim->opacity(), qreal(0));
+ QTRY_COMPARE(anim->opacity(), qreal(1));
delete anim;
delete root;
@@ -418,8 +418,8 @@ void tst_qquickanimatedimage::progressAndStatusChanges()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QCOMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
qRegisterMetaType<QQuickImageBase::Status>();
QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(QUrl)));
@@ -428,33 +428,33 @@ void tst_qquickanimatedimage::progressAndStatusChanges()
// Same image
ctxt->setContextProperty("srcImage", testFileUrl("stickman.gif"));
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 0);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 0);
// Loading local file
ctxt->setContextProperty("srcImage", testFileUrl("colors.gif"));
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 1);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 1);
// Loading remote file
ctxt->setContextProperty("srcImage", server.url("/stickman.gif"));
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
- QTRY_VERIFY(obj->progress() == 0.0);
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Loading);
+ QTRY_COMPARE(obj->progress(), 0.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 2);
QTRY_VERIFY(progressSpy.count() > 1);
QTRY_COMPARE(statusSpy.count(), 3);
ctxt->setContextProperty("srcImage", "");
- QTRY_VERIFY(obj->status() == QQuickImage::Null);
- QTRY_VERIFY(obj->progress() == 0.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Null);
+ QTRY_COMPARE(obj->progress(), 0.0);
QTRY_COMPARE(sourceSpy.count(), 3);
QTRY_VERIFY(progressSpy.count() > 2);
QTRY_COMPARE(statusSpy.count(), 4);
@@ -472,7 +472,7 @@ void tst_qquickanimatedimage::playingAndPausedChanges()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickAnimatedImage *obj = qobject_cast<QQuickAnimatedImage*>(component.create());
QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickAnimatedImage::Null);
+ QCOMPARE(obj->status(), QQuickAnimatedImage::Null);
QTRY_VERIFY(obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
QSignalSpy playingSpy(obj, SIGNAL(playingChanged()));
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index 45cfe4f334..2b805e9eeb 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -122,9 +122,9 @@ void tst_qquickanimations::simpleProperty()
animation.setTargetObject(&rect);
animation.setProperty("x");
animation.setTo(200);
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "x");
- QVERIFY(animation.to().toReal() == 200.0);
+ QCOMPARE(animation.target(), &rect);
+ QCOMPARE(animation.property(), QLatin1String("x"));
+ QCOMPARE(animation.to().toReal(), 200.0);
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -136,7 +136,7 @@ void tst_qquickanimations::simpleProperty()
animation.pause();
QVERIFY(animation.isPaused());
animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.x(),100.0);
}
@@ -147,9 +147,9 @@ void tst_qquickanimations::simpleNumber()
animation.setTargetObject(&rect);
animation.setProperty("x");
animation.setTo(200);
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "x");
- QVERIFY(animation.to() == 200);
+ QCOMPARE(animation.target(), &rect);
+ QCOMPARE(animation.property(), QLatin1String("x"));
+ QCOMPARE(animation.to(), qreal(200));
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -161,7 +161,7 @@ void tst_qquickanimations::simpleNumber()
QVERIFY(animation.isRunning());
QVERIFY(animation.isPaused());
animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.x(), qreal(100));
}
@@ -172,9 +172,9 @@ void tst_qquickanimations::simpleColor()
animation.setTargetObject(&rect);
animation.setProperty("color");
animation.setTo(QColor("red"));
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "color");
- QVERIFY(animation.to() == QColor("red"));
+ QCOMPARE(animation.target(), &rect);
+ QCOMPARE(animation.property(), QLatin1String("color"));
+ QCOMPARE(animation.to(), QColor("red"));
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -186,12 +186,12 @@ void tst_qquickanimations::simpleColor()
QVERIFY(animation.isRunning());
QVERIFY(animation.isPaused());
animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
rect.setColor(QColor("green"));
animation.setFrom(QColor("blue"));
- QVERIFY(animation.from() == QColor("blue"));
+ QCOMPARE(animation.from(), QColor("blue"));
animation.restart();
QCOMPARE(rect.color(), QColor("blue"));
QVERIFY(animation.isRunning());
@@ -206,10 +206,10 @@ void tst_qquickanimations::simpleRotation()
animation.setTargetObject(&rect);
animation.setProperty("rotation");
animation.setTo(270);
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "rotation");
- QVERIFY(animation.to() == 270);
- QVERIFY(animation.direction() == QQuickRotationAnimation::Numerical);
+ QCOMPARE(animation.target(), &rect);
+ QCOMPARE(animation.property(), QLatin1String("rotation"));
+ QCOMPARE(animation.to(), qreal(270));
+ QCOMPARE(animation.direction(), QQuickRotationAnimation::Numerical);
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -221,7 +221,7 @@ void tst_qquickanimations::simpleRotation()
QVERIFY(animation.isRunning());
QVERIFY(animation.isPaused());
animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.rotation(), qreal(135));
}
@@ -567,8 +567,8 @@ void tst_qquickanimations::alwaysRunToEnd()
animation.setDuration(1000);
animation.setLoops(-1);
animation.setAlwaysRunToEnd(true);
- QVERIFY(animation.loops() == -1);
- QVERIFY(animation.alwaysRunToEnd() == true);
+ QCOMPARE(animation.loops(), -1);
+ QVERIFY(animation.alwaysRunToEnd());
QElapsedTimer timer;
timer.start();
@@ -600,7 +600,7 @@ void tst_qquickanimations::complete()
animation.setFrom(1);
animation.setTo(200);
animation.setDuration(500);
- QVERIFY(animation.from() == 1);
+ QCOMPARE(animation.from().toInt(), 1);
animation.start();
QTest::qWait(50);
animation.stop();
@@ -620,7 +620,7 @@ void tst_qquickanimations::resume()
animation.setFrom(10);
animation.setTo(200);
animation.setDuration(1000);
- QVERIFY(animation.from() == 10);
+ QCOMPARE(animation.from().toInt(), 10);
animation.start();
QTest::qWait(400);
@@ -685,7 +685,7 @@ void tst_qquickanimations::dotProperty()
animation.start();
animation.pause();
animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.border()->width(), 5.0);
}
@@ -708,7 +708,7 @@ void tst_qquickanimations::badTypes()
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
c.create();
- QVERIFY(c.errors().count() == 1);
+ QCOMPARE(c.errors().count(), 1);
QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: number expected"));
}
@@ -719,7 +719,7 @@ void tst_qquickanimations::badTypes()
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
c.create();
- QVERIFY(c.errors().count() == 1);
+ QCOMPARE(c.errors().count(), 1);
QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected"));
}
@@ -1065,7 +1065,7 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
QVERIFY(myAnim);
- QVERIFY(myAnim->isRunning() == false);
+ QVERIFY(!myAnim->isRunning());
}
{
@@ -1078,7 +1078,7 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
QVERIFY(myAnim && !myAnim->qtAnimation());
- //QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimationJob::Stopped);
+ //QCOMPARE(myAnim->qtAnimation()->state(), QAbstractAnimationJob::Stopped);
}
}
@@ -1097,7 +1097,7 @@ void tst_qquickanimations::dontStart()
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
QVERIFY(myAnim && !myAnim->qtAnimation());
- //QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimationJob::Stopped);
+ //QCOMPARE(myAnim->qtAnimation()->state(), QAbstractAnimationJob::Stopped);
}
{
@@ -1112,7 +1112,7 @@ void tst_qquickanimations::dontStart()
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
QVERIFY(myAnim && !myAnim->qtAnimation());
- //QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimationJob::Stopped);
+ //QCOMPARE(myAnim->qtAnimation()->state(), QAbstractAnimationJob::Stopped);
}
}
@@ -1350,8 +1350,8 @@ void tst_qquickanimations::alwaysRunToEndRestartBug()
animation.setDuration(1000);
animation.setLoops(-1);
animation.setAlwaysRunToEnd(true);
- QVERIFY(animation.loops() == -1);
- QVERIFY(animation.alwaysRunToEnd() == true);
+ QCOMPARE(animation.loops(), -1);
+ QVERIFY(animation.alwaysRunToEnd());
animation.start();
animation.stop();
animation.start();
@@ -1387,7 +1387,7 @@ void tst_qquickanimations::pauseBindingBug()
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
QVERIFY(rect != 0);
QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
- QVERIFY(anim->qtAnimation()->state() == QAbstractAnimationJob::Paused);
+ QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
delete rect;
}
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index 7df020405f..1d8fc430b8 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -97,7 +97,7 @@ void tst_qquickapplication::active()
window.show();
window.requestActivate();
QTest::qWaitForWindowActive(&window);
- QVERIFY(QGuiApplication::focusWindow() == &window);
+ QCOMPARE(QGuiApplication::focusWindow(), &window);
QVERIFY(item->property("active").toBool());
QVERIFY(item->property("active2").toBool());
@@ -167,7 +167,7 @@ void tst_qquickapplication::state()
window.show();
window.requestActivate();
QTest::qWaitForWindowActive(&window);
- QVERIFY(QGuiApplication::focusWindow() == &window);
+ QCOMPARE(QGuiApplication::focusWindow(), &window);
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive);
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..071ea0b494 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()));
@@ -150,12 +157,12 @@ void tst_qquickborderimage::imageSource()
QVERIFY(obj != 0);
if (remote)
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Loading);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Loading);
QCOMPARE(obj->source(), remote ? source : QUrl(source));
if (error.isEmpty()) {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Ready);
QCOMPARE(obj->width(), 120.);
QCOMPARE(obj->height(), 120.);
QCOMPARE(obj->sourceSize().width(), 120);
@@ -163,7 +170,7 @@ void tst_qquickborderimage::imageSource()
QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
} else {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Error);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Error);
}
delete obj;
@@ -178,13 +185,13 @@ void tst_qquickborderimage::clearSource()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickBorderImage::Ready);
+ QCOMPARE(obj->status(), QQuickBorderImage::Ready);
QCOMPARE(obj->width(), 120.);
QCOMPARE(obj->height(), 120.);
ctxt->setContextProperty("srcImage", "");
QVERIFY(obj->source().isEmpty());
- QVERIFY(obj->status() == QQuickBorderImage::Null);
+ QCOMPARE(obj->status(), QQuickBorderImage::Null);
QCOMPARE(obj->width(), 0.);
QCOMPARE(obj->height(), 0.);
@@ -296,14 +303,14 @@ void tst_qquickborderimage::sciSource()
QVERIFY(obj != 0);
if (remote)
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Loading);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Loading);
QCOMPARE(obj->source(), remote ? source : QUrl(source));
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 300.);
if (valid) {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Ready);
QCOMPARE(obj->border()->left(), 10);
QCOMPARE(obj->border()->top(), 20);
QCOMPARE(obj->border()->right(), 30);
@@ -311,7 +318,7 @@ void tst_qquickborderimage::sciSource()
QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Round);
QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Repeat);
} else {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Error);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Error);
}
delete obj;
@@ -443,7 +450,7 @@ void tst_qquickborderimage::statusChanges()
obj->setSource(source);
if (remote)
server.sendDelayedItem();
- QTRY_VERIFY(obj->status() == finalStatus);
+ QTRY_COMPARE(obj->status(), finalStatus);
QCOMPARE(spy.count(), emissions);
delete obj;
@@ -529,8 +536,8 @@ void tst_qquickborderimage::progressAndStatusChanges()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickBorderImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QCOMPARE(obj->status(), QQuickBorderImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
qRegisterMetaType<QQuickBorderImage::Status>();
QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(QUrl)));
@@ -539,33 +546,33 @@ void tst_qquickborderimage::progressAndStatusChanges()
// Same file
ctxt->setContextProperty("srcImage", testFileUrl("heart200.png"));
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 0);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 0);
// Loading local file
ctxt->setContextProperty("srcImage", testFileUrl("colors.png"));
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 1);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 1);
// Loading remote file
ctxt->setContextProperty("srcImage", server.url("/heart200.png"));
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Loading);
- QTRY_VERIFY(obj->progress() == 0.0);
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Loading);
+ QTRY_COMPARE(obj->progress(), 0.0);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 2);
QTRY_VERIFY(progressSpy.count() > 1);
QTRY_COMPARE(statusSpy.count(), 3);
ctxt->setContextProperty("srcImage", "");
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Null);
- QTRY_VERIFY(obj->progress() == 0.0);
+ QTRY_COMPARE(obj->status(), QQuickBorderImage::Null);
+ QTRY_COMPARE(obj->progress(), 0.0);
QTRY_COMPARE(sourceSpy.count(), 3);
QTRY_VERIFY(progressSpy.count() > 2);
QTRY_COMPARE(statusSpy.count(), 4);
diff --git a/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml b/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
new file mode 100644
index 0000000000..68f456af99
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+Item {
+ width: 100
+ height: 62
+
+ x: Math.max(0, 200)
+}
+
diff --git a/tests/auto/quick/qquickdesignersupport/data/test.qml b/tests/auto/quick/qquickdesignersupport/data/test.qml
new file mode 100644
index 0000000000..1d43cb3b7e
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/data/test.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.0
+
+Rectangle {
+ objectName: "rootItem"
+ color: "white"
+ width: 800
+ height: 600
+
+ TestComponent {
+ objectName: "testComponent"
+
+ }
+
+ Rectangle {
+ objectName: "rectangleItem"
+ gradient: Gradient {
+
+ }
+ }
+
+ Item {
+ id: item
+ objectName: "simpleItem"
+ property string testProperty: dynamicProperty
+ }
+
+ states: [
+ State {
+ name: "state01"
+ PropertyChanges {
+ target: item
+ width: 10
+ }
+ },
+ State {
+ name: "state02"
+ }
+ ]
+}
diff --git a/tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro b/tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro
new file mode 100644
index 0000000000..af932d834b
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qquickdesignersupport
+SOURCES += tst_qquickdesignersupport.cpp
+
+include (../../shared/util.pri)
+include (../shared/util.pri)
+
+osx:CONFIG -= app_bundle
+
+TESTDATA = data/*
+
+QT += core-private gui-private qml-private quick-private testlib
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+DISTFILES += \
+ data/TestComponent.qml
diff --git a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
new file mode 100644
index 0000000000..49535783c1
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
@@ -0,0 +1,500 @@
+/****************************************************************************
+**
+** 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 <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQuick/qquickview.h>
+#include <private/qquickdesignersupportitems_p.h>
+#include <private/qquickdesignersupportmetainfo_p.h>
+#include <private/qquickdesignersupportproperties_p.h>
+#include <private/qquickdesignersupportstates_p.h>
+#include <private/qquickdesignersupportpropertychanges_p.h>
+#include <private/qquickitem_p.h>
+#include <private/qquickstate_p.h>
+#include <private/qquickstate_p_p.h>
+#include <private/qquickstategroup_p.h>
+#include <private/qquickpropertychanges_p.h>
+#include <private/qquickrectangle_p.h>
+#include "../../shared/util.h"
+#include "../shared/visualtestutil.h"
+
+using namespace QQuickVisualTestUtil;
+
+class tst_qquickdesignersupport : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qquickdesignersupport() {}
+
+private slots:
+ void customData();
+ void customDataBindings();
+ void objectProperties();
+ void dynamicProperty();
+ void createComponent();
+ void basicStates();
+ void statesPropertyChanges();
+ void testNotifyPropertyChangeCallBack();
+ void testFixResourcePathsForObjectCallBack();
+};
+
+void tst_qquickdesignersupport::customData()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QScopedPointer<QObject> newItemScopedPointer(QQuickDesignerSupportItems::createPrimitive(QLatin1String("QtQuick/Item"), 2, 6, view->rootContext()));
+ QObject *newItem = newItemScopedPointer.data();
+
+ QVERIFY(newItem);
+ QVERIFY(qobject_cast<QQuickItem*>(newItem));
+
+ QQuickDesignerSupportProperties::registerCustomData(newItem);
+ QVERIFY(QQuickDesignerSupportProperties::getResetValue(newItem, "width").isValid());
+ int defaultWidth = QQuickDesignerSupportProperties::getResetValue(newItem, "width").toInt();
+ QCOMPARE(defaultWidth, 0);
+
+ newItem->setProperty("width", 200);
+ QCOMPARE(newItem->property("width").toInt(), 200);
+
+ //Check if reseting property does work
+ QQuickDesignerSupportProperties::doResetProperty(newItem, view->rootContext(), "width");
+ QCOMPARE(newItem->property("width").toInt(), 0);
+
+ //Setting a binding on width
+ QQuickDesignerSupportProperties::setPropertyBinding(newItem,
+ view->engine()->contextForObject(newItem),
+ "width",
+ QLatin1String("Math.max(0, 200)"));
+ QCOMPARE(newItem->property("width").toInt(), 200);
+ QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(newItem,
+ view->engine()->contextForObject(newItem),
+ "width",
+ 0));
+
+ //Check if reseting property does work after setting binding
+ QQuickDesignerSupportProperties::doResetProperty(newItem, view->rootContext(), "width");
+ QCOMPARE(newItem->property("width").toInt(), 0);
+
+ //No custom data available for the rootItem, because not registered by QQuickDesignerSupportProperties::registerCustomData
+ QVERIFY(!QQuickDesignerSupportProperties::getResetValue(rootItem, "width").isValid());
+
+ newItemScopedPointer.reset(); //Delete the item and check if item gets removed from the hash and an invalid QVariant is returned.
+
+ QVERIFY(!QQuickDesignerSupportProperties::getResetValue(newItem, "width").isValid());
+}
+
+void tst_qquickdesignersupport::customDataBindings()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QQuickItem *testComponent = findItem<QQuickItem>(view->rootObject(), QLatin1String("testComponent"));
+
+ QVERIFY(testComponent);
+ QQuickDesignerSupportProperties::registerCustomData(testComponent);
+ QQuickDesignerSupportProperties::hasValidResetBinding(testComponent, "x");
+ QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x",
+ 0));
+
+ QCOMPARE(testComponent->property("x").toInt(), 200);
+
+
+ //Set property to 100 and ovveride the default binding
+ QQmlProperty property(testComponent, "x", view->engine()->contextForObject(testComponent));
+ QVERIFY(property.write(100));
+ QCOMPARE(testComponent->property("x").toInt(), 100);
+
+ QVERIFY(!QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x",
+ 0));
+
+ //Reset the binding to the default
+ QQuickDesignerSupportProperties::doResetProperty(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x");
+
+ QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x",
+ 0));
+ QCOMPARE(testComponent->property("x").toInt(), 200);
+
+
+
+ //Set a different binding/expression
+ QQuickDesignerSupportProperties::setPropertyBinding(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x",
+ QLatin1String("Math.max(0, 300)"));
+
+ QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x",
+ 0));
+
+ QCOMPARE(testComponent->property("x").toInt(), 300);
+
+
+
+ //Reset the binding to the default
+ QQuickDesignerSupportProperties::doResetProperty(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x");
+
+
+ QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
+ view->engine()->contextForObject(testComponent),
+ "x",
+ 0));
+ QCOMPARE(testComponent->property("x").toInt(), 200);
+}
+
+void tst_qquickdesignersupport::objectProperties()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QQuickItem *rectangleItem = findItem<QQuickItem>(view->rootObject(), QLatin1String("rectangleItem"));
+ QVERIFY(rectangleItem);
+
+
+ //Read gradient property as QObject
+ int propertyIndex = rectangleItem->metaObject()->indexOfProperty("gradient");
+ QVERIFY(propertyIndex > 0);
+ QMetaProperty metaProperty = rectangleItem->metaObject()->property(propertyIndex);
+ QVERIFY(metaProperty.isValid());
+
+ QVERIFY(QQuickDesignerSupportProperties::isPropertyQObject(metaProperty));
+
+ QObject*gradient = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, rectangleItem);
+ QVERIFY(gradient);
+
+
+ //The width property is not a QObject
+ propertyIndex = rectangleItem->metaObject()->indexOfProperty("width");
+ QVERIFY(propertyIndex > 0);
+ metaProperty = rectangleItem->metaObject()->property(propertyIndex);
+ QVERIFY(metaProperty.isValid());
+ QVERIFY(!QQuickDesignerSupportProperties::isPropertyQObject(metaProperty));
+}
+
+void tst_qquickdesignersupport::dynamicProperty()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QQuickItem *simpleItem = findItem<QQuickItem>(view->rootObject(), QLatin1String("simpleItem"));
+
+ QVERIFY(simpleItem);
+
+ QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(simpleItem, view->engine());
+ QQuickDesignerSupportProperties::getPropertyCache(simpleItem, view->engine());
+
+ QQuickDesignerSupportProperties::createNewDynamicProperty(simpleItem, view->engine(), QLatin1String("dynamicProperty"));
+
+ QQmlProperty property(simpleItem, "dynamicProperty", view->engine()->contextForObject(simpleItem));
+ QVERIFY(property.isValid());
+ QVERIFY(property.write(QLatin1String("test")));
+
+
+ QCOMPARE(property.read().toString(), QLatin1String("test"));
+
+ //Force evalutation of all bindings
+ QQuickDesignerSupport::refreshExpressions(view->rootContext());
+
+ //Check if expression to dynamic property gets properly resolved
+ property = QQmlProperty(simpleItem, "testProperty", view->engine()->contextForObject(simpleItem));
+ QVERIFY(property.isValid());
+ QCOMPARE(property.read().toString(), QLatin1String("test"));
+}
+
+void tst_qquickdesignersupport::createComponent()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QObject *testComponentObject = QQuickDesignerSupportItems::createComponent(testFileUrl("TestComponent.qml"), view->rootContext());
+ QVERIFY(testComponentObject);
+
+ QVERIFY(QQuickDesignerSupportMetaInfo::isSubclassOf(testComponentObject, "QtQuick/Item"));
+}
+
+void tst_qquickdesignersupport::basicStates()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QQuickStateGroup *stateGroup = QQuickItemPrivate::get(rootItem)->_states();
+
+ QVERIFY(stateGroup);
+
+ QCOMPARE(stateGroup->states().count(), 2 );
+
+ QQuickState *state01 = stateGroup->states().first();
+ QQuickState *state02 = stateGroup->states().last();
+
+ QVERIFY(state01);
+ QVERIFY(state02);
+
+ QCOMPARE(state01->property("name").toString(), QLatin1String("state01"));
+ QCOMPARE(state02->property("name").toString(), QLatin1String("state02"));
+
+ QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext()));
+ QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext()));
+
+ QQuickDesignerSupportStates::activateState(state01, view->rootContext());
+ QVERIFY(QQuickDesignerSupportStates::isStateActive(state01, view->rootContext()));
+
+ QQuickDesignerSupportStates::activateState(state02, view->rootContext());
+ QVERIFY(QQuickDesignerSupportStates::isStateActive(state02, view->rootContext()));
+ QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext()));
+
+ QQuickDesignerSupportStates::deactivateState(state02);
+ QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext()));
+ QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext()));
+}
+
+void tst_qquickdesignersupport::statesPropertyChanges()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QQuickItem *simpleItem = findItem<QQuickItem>(view->rootObject(), QLatin1String("simpleItem"));
+
+ QVERIFY(simpleItem);
+
+ QQuickStateGroup *stateGroup = QQuickItemPrivate::get(rootItem)->_states();
+
+ QVERIFY(stateGroup);
+
+ QCOMPARE(stateGroup->states().count(), 2 );
+
+ QQuickState *state01 = stateGroup->states().first();
+ QQuickState *state02 = stateGroup->states().last();
+
+ QVERIFY(state01);
+ QVERIFY(state02);
+
+ QCOMPARE(state01->property("name").toString(), QLatin1String("state01"));
+ QCOMPARE(state02->property("name").toString(), QLatin1String("state02"));
+
+ //PropertyChanges are parsed lazily
+ QQuickDesignerSupportStates::activateState(state01, view->rootContext());
+ QQuickDesignerSupportStates::deactivateState(state01);
+
+ QQuickStatePrivate *statePrivate01 = static_cast<QQuickStatePrivate *>(QQuickStatePrivate::get(state01));
+
+ QCOMPARE(state01->operationCount(), 1);
+
+ QCOMPARE(statePrivate01->operations.count(), 1);
+
+ QQuickStateOperation *propertyChange = statePrivate01->operations.at(0).data();
+
+ QCOMPARE(QQuickDesignerSupportPropertyChanges::stateObject(propertyChange), state01);
+
+ QQuickDesignerSupportPropertyChanges::changeValue(propertyChange, "width", 300);
+
+ QCOMPARE(simpleItem->property("width").toInt(), 0);
+ QQuickDesignerSupportStates::activateState(state01, view->rootContext());
+ QCOMPARE(simpleItem->property("width").toInt(), 300);
+ QQuickDesignerSupportStates::deactivateState(state01);
+ QCOMPARE(simpleItem->property("width").toInt(), 0);
+
+ //Set "base state value" in state1 using the revert list
+ QQuickDesignerSupportStates::activateState(state01, view->rootContext());
+ QQuickDesignerSupportStates::changeValueInRevertList(state01, simpleItem, "width", 200);
+ QCOMPARE(simpleItem->property("width").toInt(), 300);
+ QQuickDesignerSupportStates::deactivateState(state01);
+ QCOMPARE(simpleItem->property("width").toInt(), 200);
+
+
+ //Create new PropertyChanges
+ QQuickPropertyChanges *newPropertyChange = new QQuickPropertyChanges();
+ newPropertyChange->setParent(state01);
+ QQuickStatePrivate::operations_append(&state01->changes(), newPropertyChange);
+
+ newPropertyChange->setObject(rootItem);
+
+ QQuickDesignerSupportPropertyChanges::attachToState(newPropertyChange);
+
+ QCOMPARE(rootItem, QQuickDesignerSupportPropertyChanges::targetObject(newPropertyChange));
+
+ QCOMPARE(state01->operationCount(), 2);
+ QCOMPARE(statePrivate01->operations.count(), 2);
+
+ QCOMPARE(QQuickDesignerSupportPropertyChanges::stateObject(newPropertyChange), state01);
+
+ //Set color for rootItem in state1
+ QQuickDesignerSupportPropertyChanges::changeValue(newPropertyChange, "color", QColor(Qt::red));
+
+ QQuickDesignerSupportStates::activateState(state01, view->rootContext());
+ QCOMPARE(rootItem->property("color").value<QColor>(), QColor(Qt::red));
+ QQuickDesignerSupportStates::deactivateState(state01);
+ QCOMPARE(rootItem->property("color").value<QColor>(), QColor(Qt::white));
+
+ QQuickDesignerSupportPropertyChanges::removeProperty(newPropertyChange, "color");
+ QQuickDesignerSupportStates::activateState(state01, view->rootContext());
+ QCOMPARE(rootItem->property("color").value<QColor>(), QColor(Qt::white));
+
+}
+
+static QObject * s_object = 0;
+static QQuickDesignerSupport::PropertyName s_propertyName;
+
+static void notifyPropertyChangeCallBackFunction(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ s_object = object;
+ s_propertyName = propertyName;
+}
+
+static void (*notifyPropertyChangeCallBackPointer)(QObject *, const QQuickDesignerSupport::PropertyName &) = &notifyPropertyChangeCallBackFunction;
+
+
+void tst_qquickdesignersupport::testNotifyPropertyChangeCallBack()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ QQuickRectangle *rectangle = static_cast<QQuickRectangle *>(rootItem);
+ QVERIFY(rectangle);
+
+ QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(rectangle, view->engine());
+
+ QQuickGradient *gradient = new QQuickGradient(rectangle);
+
+ QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(notifyPropertyChangeCallBackPointer);
+
+ rectangle->setProperty("gradient", QVariant::fromValue<QQuickGradient *>(gradient));
+
+ QVERIFY(s_object);
+ QCOMPARE(s_object, rootItem);
+ QCOMPARE(s_propertyName, QQuickDesignerSupport::PropertyName("gradient"));
+}
+
+static void fixResourcePathsForObjectCallBackFunction(QObject *object)
+{
+ s_object = object;
+}
+
+static void (*fixResourcePathsForObjectCallBackPointer)(QObject *) = &fixResourcePathsForObjectCallBackFunction;
+
+void tst_qquickdesignersupport::testFixResourcePathsForObjectCallBack()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("test.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+
+ QQuickItem *rootItem = view->rootObject();
+
+ QVERIFY(rootItem);
+
+ s_object = 0;
+
+ QQuickDesignerSupportItems::registerFixResourcePathsForObjectCallBack(fixResourcePathsForObjectCallBackPointer);
+
+ QQuickItem *simpleItem = findItem<QQuickItem>(view->rootObject(), QLatin1String("simpleItem"));
+
+ QVERIFY(simpleItem);
+
+ QQuickDesignerSupportItems::tweakObjects(simpleItem);
+
+ //Check that the fixResourcePathsForObjectCallBack was called on simpleItem
+ QCOMPARE(simpleItem , s_object);
+}
+
+
+QTEST_MAIN(tst_qquickdesignersupport)
+
+#include "tst_qquickdesignersupport.moc"
diff --git a/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp b/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp
index 40bd6624f0..3656bb8aab 100644
--- a/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp
+++ b/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp
@@ -59,11 +59,11 @@ private:
QQmlProperty testProp(item, propertyName);
QPropertyAnimation animation(item, propertyName, this);
animation.setEndValue(toValue);
- QVERIFY(animation.targetObject() == item);
- QVERIFY(animation.propertyName() == propertyName);
- QVERIFY(animation.endValue().value<T>() == toValue);
+ QCOMPARE(animation.targetObject(), item);
+ QCOMPARE(animation.propertyName(), propertyName);
+ QCOMPARE(animation.endValue().value<T>(), toValue);
animation.start();
- QVERIFY(animation.state() == QAbstractAnimation::Running);
+ QCOMPARE(animation.state(), QAbstractAnimation::Running);
QTest::qWait(animation.duration());
QTRY_COMPARE(testProp.read().value<T>(), toValue);
}
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/data/movementSignals.qml b/tests/auto/quick/qquickflickable/data/movementSignals.qml
new file mode 100644
index 0000000000..581e882139
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/movementSignals.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+
+Flickable {
+ width: 400; height: 400
+ contentWidth: 400; contentHeight: 1200
+
+ property string signalString
+
+ Rectangle {
+ width: 400; height: 400
+ color: "red"
+ }
+ Rectangle {
+ y: 400; width: 400; height: 400
+ color: "yellow"
+ }
+ Rectangle {
+ y: 800; width: 400; height: 400
+ color: "green"
+ }
+
+ onMovementStarted: signalString += "ms"
+ onMovementEnded: signalString += "me"
+ onFlickStarted: signalString += "fs"
+ onFlickEnded: signalString += "fe"
+}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 7d08c3c81e..eee7ffe560 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -91,6 +91,7 @@ private slots:
void stopAtBounds_data();
void nestedMouseAreaUsingTouch();
void pressDelayWithLoader();
+ void movementFromProgrammaticFlick();
void cleanup();
private:
@@ -195,9 +196,9 @@ void tst_qquickflickable::properties()
QCOMPARE(obj->pressDelay(), 200);
QCOMPARE(obj->maximumFlickVelocity(), 2000.);
- QVERIFY(obj->property("ok").toBool() == false);
+ QVERIFY(!obj->property("ok").toBool());
QMetaObject::invokeMethod(obj, "check");
- QVERIFY(obj->property("ok").toBool() == true);
+ QVERIFY(obj->property("ok").toBool());
delete obj;
}
@@ -211,28 +212,28 @@ void tst_qquickflickable::boundsBehavior()
QSignalSpy spy(flickable, SIGNAL(boundsBehaviorChanged()));
QVERIFY(flickable);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
+ QCOMPARE(flickable->boundsBehavior(), QQuickFlickable::StopAtBounds);
flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragAndOvershootBounds);
+ QCOMPARE(flickable->boundsBehavior(), QQuickFlickable::DragAndOvershootBounds);
QCOMPARE(spy.count(),1);
flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
QCOMPARE(spy.count(),1);
flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragOverBounds);
+ QCOMPARE(flickable->boundsBehavior(), QQuickFlickable::DragOverBounds);
QCOMPARE(spy.count(),2);
flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
QCOMPARE(spy.count(),2);
flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
+ QCOMPARE(flickable->boundsBehavior(), QQuickFlickable::StopAtBounds);
QCOMPARE(spy.count(),3);
flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
QCOMPARE(spy.count(),3);
flickable->setBoundsBehavior(QQuickFlickable::OvershootBounds);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::OvershootBounds);
+ QCOMPARE(flickable->boundsBehavior(), QQuickFlickable::OvershootBounds);
QCOMPARE(spy.count(),4);
flickable->setBoundsBehavior(QQuickFlickable::OvershootBounds);
QCOMPARE(spy.count(),4);
@@ -249,7 +250,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 +296,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 +389,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,13 +407,13 @@ 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);
+ QVERIFY(!mouseArea->property("pressed").toBool());
// But, it should occur eventually
- QTRY_VERIFY(mouseArea->property("pressed").toBool() == true);
+ QTRY_VERIFY(mouseArea->property("pressed").toBool());
QCOMPARE(clickedSpy.count(),0);
@@ -427,10 +428,10 @@ 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);
+ QVERIFY(!mouseArea->property("pressed").toBool());
QCOMPARE(clickedSpy.count(),0);
@@ -444,16 +445,16 @@ 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);
+ QVERIFY(!mouseArea->property("pressed").toBool());
QTest::mouseMove(window.data(), QPoint(150, 190));
// As we moved pass the drag threshold, we should never receive the press
- QVERIFY(mouseArea->property("pressed").toBool() == false);
- QTRY_VERIFY(mouseArea->property("pressed").toBool() == false);
+ QVERIFY(!mouseArea->property("pressed").toBool());
+ QTRY_VERIFY(!mouseArea->property("pressed").toBool());
// On release the clicked signal should *not* be emitted
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 190));
@@ -469,7 +470,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,44 +479,44 @@ 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);
+ QVERIFY(!outer->property("pressed").toBool());
+ QVERIFY(!inner->property("pressed").toBool());
// The inner pressDelay will prevail (50ms, vs. 10sec)
// QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec.
- QTRY_VERIFY(outer->property("pressed").toBool() == true);
+ QTRY_VERIFY(outer->property("pressed").toBool());
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);
+ QVERIFY(!outer->property("pressed").toBool());
+ QVERIFY(!inner->property("pressed").toBool());
QTest::mouseMove(window.data(), QPoint(60, 150));
QTest::mouseMove(window.data(), QPoint(40, 150));
QTest::mouseMove(window.data(), QPoint(20, 150));
- QVERIFY(inner->property("moving").toBool() == true);
- QVERIFY(outer->property("moving").toBool() == false);
+ QVERIFY(inner->property("moving").toBool());
+ QVERIFY(!outer->property("moving").toBool());
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);
+ QVERIFY(!outer->property("pressed").toBool());
QTest::mouseMove(window.data(), QPoint(130, 150));
QTest::mouseMove(window.data(), QPoint(110, 150));
QTest::mouseMove(window.data(), QPoint(90, 150));
- QVERIFY(outer->property("moving").toBool() == false);
- QVERIFY(inner->property("moving").toBool() == true);
+ QVERIFY(!outer->property("moving").toBool());
+ QVERIFY(inner->property("moving").toBool());
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(90, 150));
}
@@ -529,7 +530,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,29 +539,29 @@ 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);
- QTRY_VERIFY(outer->property("pressed").toBool() == true);
+ QVERIFY(!outer->property("pressed").toBool());
+ QTRY_VERIFY(outer->property("pressed").toBool());
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
- QVERIFY(outer->property("pressed").toBool() == false);
+ QVERIFY(!outer->property("pressed").toBool());
// 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(!outer->property("pressed").toBool());
QTest::mouseMove(window.data(), QPoint(80, 148));
QTest::mouseMove(window.data(), QPoint(80, 140));
QTest::mouseMove(window.data(), QPoint(80, 120));
QTest::mouseMove(window.data(), QPoint(80, 100));
- QVERIFY(outer->property("moving").toBool() == false);
- QVERIFY(inner->property("moving").toBool() == true);
+ QVERIFY(!outer->property("moving").toBool());
+ QVERIFY(inner->property("moving").toBool());
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(80, 100));
}
@@ -628,6 +629,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 +674,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");
@@ -685,10 +688,10 @@ void tst_qquickflickable::wheel()
}
QTRY_VERIFY(flick->contentY() > 0);
- QVERIFY(flick->contentX() == 0);
+ QCOMPARE(flick->contentX(), qreal(0));
flick->setContentY(0);
- QVERIFY(flick->contentY() == 0);
+ QCOMPARE(flick->contentY(), qreal(0));
{
QPoint pos(200, 200);
@@ -699,7 +702,7 @@ void tst_qquickflickable::wheel()
}
QTRY_VERIFY(flick->contentX() > 0);
- QVERIFY(flick->contentY() == 0);
+ QCOMPARE(flick->contentY(), qreal(0));
}
void tst_qquickflickable::movingAndFlicking_data()
@@ -740,7 +743,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 +906,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 +925,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);
@@ -962,7 +965,7 @@ void tst_qquickflickable::movingAndDragging()
// Don't test whether moving finished because a flick could occur
// wait for any motion to end
- QTRY_VERIFY(flickable->isMoving() == false);
+ QTRY_VERIFY(!flickable->isMoving());
QVERIFY(!flickable->isMovingHorizontally());
QVERIFY(!flickable->isMovingVertically());
@@ -998,7 +1001,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 +1075,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,14 +1088,14 @@ 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);
QCOMPARE(vFlickSpy.count(), 1);
// wait for any motion to end
- QTRY_VERIFY(flickable->isMoving() == false);
+ QTRY_VERIFY(!flickable->isMoving());
#ifdef Q_OS_MAC
QEXPECT_FAIL("", "QTBUG-26094 stopping on a full pixel doesn't work on OS X", Continue);
@@ -1109,7 +1112,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,27 +1162,27 @@ 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));
QTest::mouseMove(window.data(), QPoint(50, 60));
- QVERIFY(flick->isMoving() == false);
+ QVERIFY(!flick->isMoving());
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);
+ QTRY_VERIFY(window->rootObject()->property("clicked").toBool());
}
void tst_qquickflickable::flickVelocity()
@@ -1190,7 +1193,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());
@@ -1199,12 +1202,12 @@ void tst_qquickflickable::flickVelocity()
// flick up
flick(window.data(), QPoint(20,190), QPoint(20, 50), 200);
QVERIFY(flickable->verticalVelocity() > 0.0);
- QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+ QTRY_COMPARE(flickable->verticalVelocity(), 0.0);
// flick down
flick(window.data(), QPoint(20,10), QPoint(20, 140), 200);
QTRY_VERIFY(flickable->verticalVelocity() < 0.0);
- QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+ QTRY_COMPARE(flickable->verticalVelocity(), 0.0);
#ifdef Q_OS_MAC
QSKIP("boost doesn't work on OS X");
@@ -1223,7 +1226,7 @@ void tst_qquickflickable::flickVelocity()
// Flick in opposite direction -> boost cancelled.
flick(window.data(), QPoint(20,10), QPoint(20, 340), 200);
QTRY_VERIFY(flickable->verticalVelocity() < 0.0);
- QVERIFY(fp->flickBoost == 1.0);
+ QCOMPARE(fp->flickBoost, 1.0);
}
void tst_qquickflickable::margins()
@@ -1235,7 +1238,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 +1301,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 +1327,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 +1339,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 +1462,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 +1492,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 +1510,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 +1529,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 +1546,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 +1586,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 +1604,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 +1652,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,14 +1712,33 @@ 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));
}
+// QTBUG-34507
+void tst_qquickflickable::movementFromProgrammaticFlick()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("movementSignals.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable != 0);
+
+ // verify that the signals for movement and flicking are called in the right order
+ flickable->flick(0, -1000);
+ QTRY_COMPARE(flickable->property("signalString").toString(), QString("msfsfeme"));
+}
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"
diff --git a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
index 76bf509cf0..2eb8942eee 100644
--- a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
+++ b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
@@ -108,11 +108,11 @@ void tst_qquickflipable::flipFlipable()
QQmlComponent c(&engine, testFileUrl("flip-flipable.qml"));
QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
QVERIFY(obj != 0);
- QVERIFY(obj->side() == QQuickFlipable::Front);
+ QCOMPARE(obj->side(), QQuickFlipable::Front);
obj->setProperty("flipped", QVariant(true));
- QTRY_VERIFY(obj->side() == QQuickFlipable::Back);
- QTRY_VERIFY(obj->side() == QQuickFlipable::Front);
- QTRY_VERIFY(obj->side() == QQuickFlipable::Back);
+ QTRY_COMPARE(obj->side(), QQuickFlipable::Back);
+ QTRY_COMPARE(obj->side(), QQuickFlipable::Front);
+ QTRY_COMPARE(obj->side(), QQuickFlipable::Back);
delete obj;
}
diff --git a/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp b/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
index 98f85af92e..4b377f92d6 100644
--- a/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
+++ b/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
@@ -81,27 +81,27 @@ void tst_qquickfocusscope::basic()
view->requestActivate();
QTest::qWaitForWindowActive(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
QVERIFY(view->isTopLevel());
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(item0->hasActiveFocus());
+ QVERIFY(item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
QTest::keyClick(view, Qt::Key_Right);
QTest::qWait(50);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == true);
- QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
QTest::keyClick(view, Qt::Key_Down);
QTest::qWait(50);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == true);
+ QVERIFY(!item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(item3->hasActiveFocus());
delete view;
}
@@ -126,13 +126,13 @@ void tst_qquickfocusscope::nested()
view->requestActivate();
QTest::qWaitForWindowActive(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == true);
- QVERIFY(item3->hasActiveFocus() == true);
- QVERIFY(item4->hasActiveFocus() == true);
- QVERIFY(item5->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus());
+ QVERIFY(item2->hasActiveFocus());
+ QVERIFY(item3->hasActiveFocus());
+ QVERIFY(item4->hasActiveFocus());
+ QVERIFY(item5->hasActiveFocus());
delete view;
}
@@ -153,24 +153,24 @@ void tst_qquickfocusscope::noFocus()
view->show();
view->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(view));
- QVERIFY(view == qGuiApp->focusWindow());
+ QCOMPARE(view, qGuiApp->focusWindow());
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(!item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
QTest::keyClick(view, Qt::Key_Right);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(!item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
QTest::keyClick(view, Qt::Key_Down);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(!item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
delete view;
}
@@ -194,33 +194,33 @@ void tst_qquickfocusscope::textEdit()
QTest::qWaitForWindowActive(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
+ QVERIFY(item0->hasActiveFocus());
+ QVERIFY(item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
QTest::keyClick(view, Qt::Key_Right);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(item0->hasActiveFocus());
+ QVERIFY(item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
QTest::keyClick(view, Qt::Key_Right);
QTest::keyClick(view, Qt::Key_Right);
QTest::keyClick(view, Qt::Key_Right);
QTest::keyClick(view, Qt::Key_Right);
QTest::keyClick(view, Qt::Key_Right);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == true);
- QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
QTest::keyClick(view, Qt::Key_Down);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == true);
+ QVERIFY(!item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(item3->hasActiveFocus());
delete view;
}
@@ -246,30 +246,30 @@ void tst_qquickfocusscope::forceFocus()
view->show();
view->requestActivate();
QTest::qWaitForWindowActive(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
- QVERIFY(item4->hasActiveFocus() == false);
- QVERIFY(item5->hasActiveFocus() == false);
+ QVERIFY(item0->hasActiveFocus());
+ QVERIFY(item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
+ QVERIFY(!item4->hasActiveFocus());
+ QVERIFY(!item5->hasActiveFocus());
QTest::keyClick(view, Qt::Key_4);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
- QVERIFY(item4->hasActiveFocus() == false);
- QVERIFY(item5->hasActiveFocus() == false);
+ QVERIFY(item0->hasActiveFocus());
+ QVERIFY(item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(!item3->hasActiveFocus());
+ QVERIFY(!item4->hasActiveFocus());
+ QVERIFY(!item5->hasActiveFocus());
QTest::keyClick(view, Qt::Key_5);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == true);
- QVERIFY(item4->hasActiveFocus() == false);
- QVERIFY(item5->hasActiveFocus() == true);
+ QVERIFY(!item0->hasActiveFocus());
+ QVERIFY(!item1->hasActiveFocus());
+ QVERIFY(!item2->hasActiveFocus());
+ QVERIFY(item3->hasActiveFocus());
+ QVERIFY(!item4->hasActiveFocus());
+ QVERIFY(item5->hasActiveFocus());
delete view;
}
@@ -283,13 +283,13 @@ void tst_qquickfocusscope::noParentFocus()
view->show();
view->requestActivate();
QTest::qWaitForWindowActive(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
- QVERIFY(view->rootObject()->property("focus1") == false);
- QVERIFY(view->rootObject()->property("focus2") == false);
- QVERIFY(view->rootObject()->property("focus3") == true);
- QVERIFY(view->rootObject()->property("focus4") == true);
- QVERIFY(view->rootObject()->property("focus5") == true);
+ QVERIFY(!view->rootObject()->property("focus1").toBool());
+ QVERIFY(!view->rootObject()->property("focus2").toBool());
+ QVERIFY(view->rootObject()->property("focus3").toBool());
+ QVERIFY(view->rootObject()->property("focus4").toBool());
+ QVERIFY(view->rootObject()->property("focus5").toBool());
delete view;
}
@@ -312,7 +312,7 @@ void tst_qquickfocusscope::signalEmission()
view->requestActivate();
QTest::qWaitForWindowActive(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
QVariant blue(QColor("blue"));
QVariant red(QColor("red"));
@@ -362,7 +362,7 @@ void tst_qquickfocusscope::qtBug13380()
QVERIFY(QTest::qWaitForWindowExposed(view));
- QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
QVERIFY(view->rootObject()->property("noFocus").toBool());
view->rootObject()->setProperty("showRect", true);
@@ -379,7 +379,7 @@ void tst_qquickfocusscope::forceActiveFocus()
view->show();
view->requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(view));
- QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QTRY_COMPARE(view, qGuiApp->focusWindow());
QQuickItem *rootObject = view->rootObject();
QVERIFY(rootObject);
@@ -532,7 +532,7 @@ void tst_qquickfocusscope::canvasFocus()
view->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(view));
- QVERIFY(view == qGuiApp->focusWindow());
+ QCOMPARE(view, qGuiApp->focusWindow());
// Now the window has focus, active focus given to item1
QCOMPARE(rootItem->hasFocus(), true);
@@ -558,7 +558,7 @@ void tst_qquickfocusscope::canvasFocus()
alternateView.show();
alternateView.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&alternateView));
- QVERIFY(QGuiApplication::focusWindow() == &alternateView);
+ QCOMPARE(QGuiApplication::focusWindow(), &alternateView);
QCOMPARE(rootItem->hasFocus(), false);
QCOMPARE(rootItem->hasActiveFocus(), false);
@@ -604,7 +604,7 @@ void tst_qquickfocusscope::canvasFocus()
view->show();
view->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(view));
- QVERIFY(QGuiApplication::focusWindow() == view);
+ QCOMPARE(QGuiApplication::focusWindow(), view);
QCOMPARE(rootItem->hasFocus(), true);
QCOMPARE(rootItem->hasActiveFocus(), true);
diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
index a084c86a95..f4f1e290c1 100644
--- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
+++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
@@ -85,7 +85,7 @@ void tst_qquickfontloader::noFont()
QVERIFY(fontObject != 0);
QCOMPARE(fontObject->name(), QString(""));
QCOMPARE(fontObject->source(), QUrl(""));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Null);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Null);
delete fontObject;
}
@@ -100,7 +100,7 @@ void tst_qquickfontloader::namedFont()
QVERIFY(fontObject != 0);
QCOMPARE(fontObject->source(), QUrl(""));
QCOMPARE(fontObject->name(), QString("Helvetica"));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
}
void tst_qquickfontloader::localFont()
@@ -113,7 +113,7 @@ void tst_qquickfontloader::localFont()
QVERIFY(fontObject != 0);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
}
void tst_qquickfontloader::failLocalFont()
@@ -127,7 +127,7 @@ void tst_qquickfontloader::failLocalFont()
QVERIFY(fontObject != 0);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString(""));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Error);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Error);
}
void tst_qquickfontloader::webFont()
@@ -141,7 +141,7 @@ void tst_qquickfontloader::webFont()
QVERIFY(fontObject != 0);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
}
void tst_qquickfontloader::redirWebFont()
@@ -157,7 +157,7 @@ void tst_qquickfontloader::redirWebFont()
QVERIFY(fontObject != 0);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
}
void tst_qquickfontloader::failWebFont()
@@ -172,7 +172,7 @@ void tst_qquickfontloader::failWebFont()
QVERIFY(fontObject != 0);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString(""));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Error);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Error);
}
void tst_qquickfontloader::changeFont()
@@ -189,26 +189,26 @@ void tst_qquickfontloader::changeFont()
QSignalSpy nameSpy(fontObject, SIGNAL(nameChanged()));
QSignalSpy statusSpy(fontObject, SIGNAL(statusChanged()));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
QCOMPARE(nameSpy.count(), 0);
QCOMPARE(statusSpy.count(), 0);
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
ctxt->setContextProperty("font", server.urlString("/daniel.ttf"));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Loading);
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Loading);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
QCOMPARE(nameSpy.count(), 1);
QCOMPARE(statusSpy.count(), 2);
QTRY_COMPARE(fontObject->name(), QString("Daniel"));
ctxt->setContextProperty("font", testFileUrl("tarzeau_ocr_a.ttf"));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
QCOMPARE(nameSpy.count(), 2);
QCOMPARE(statusSpy.count(), 2);
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
ctxt->setContextProperty("font", server.urlString("/daniel.ttf"));
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
QCOMPARE(nameSpy.count(), 3);
QCOMPARE(statusSpy.count(), 2);
QTRY_COMPARE(fontObject->name(), QString("Daniel"));
@@ -224,7 +224,7 @@ void tst_qquickfontloader::changeFontSourceViaState()
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(qvariant_cast<QObject *>(window.rootObject()->property("fontloader")));
QVERIFY(fontObject != 0);
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
@@ -236,7 +236,7 @@ void tst_qquickfontloader::changeFontSourceViaState()
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QEXPECT_FAIL("", "QTBUG-20268", Abort);
- QTRY_VERIFY(fontObject->status() == QQuickFontLoader::Ready);
+ QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
QCOMPARE(window.rootObject()->property("name").toString(), QString("Tahoma"));
}
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/data/qtbug45640.qml b/tests/auto/quick/qquickgridview/data/qtbug45640.qml
new file mode 100644
index 0000000000..6973773432
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/qtbug45640.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+
+GridView {
+ id: gridView
+ width: 400; height: 400
+ cellHeight: 100
+ cellWidth: 100
+ model: 32
+
+ topMargin: 50
+ snapMode: GridView.SnapToRow
+ preferredHighlightBegin: 50
+ preferredHighlightEnd: 50
+ highlightRangeMode: GridView.ApplyRange
+
+ delegate: Rectangle {
+ width: 100
+ height: 100
+ color: index % 2 == 0 ? "#FFFF00" : "#0000FF"
+ }
+
+ highlight: Rectangle { color: "red"; z: 2 }
+ highlightMoveDuration: 1000
+}
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 9472407e01..87042ca7ba 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -206,6 +206,11 @@ private slots:
void jsArrayChange();
+ void contentHeightWithDelayRemove_data();
+ void contentHeightWithDelayRemove();
+
+ void QTBUG_45640();
+
private:
QList<int> toIntList(const QVariantList &list);
void matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes);
@@ -373,7 +378,7 @@ void tst_QQuickGridView::items()
ctxt->setContextProperty("testModel", &model2);
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QTRY_VERIFY(itemCount == 0);
+ QTRY_COMPARE(itemCount, 0);
delete window;
}
@@ -473,8 +478,8 @@ void tst_QQuickGridView::inserted_basic()
// Confirm items positioned correctly
for (int i = 0; i < model.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
}
for (int i = model.count(); i < 30; ++i)
@@ -485,7 +490,7 @@ void tst_QQuickGridView::inserted_basic()
// Insert item outside visible area
model.insertItem(1, "Hello", "1324");
- QTRY_VERIFY(gridview->contentY() == 120);
+ QTRY_COMPARE(gridview->contentY(), qreal(120));
delete window;
}
@@ -815,8 +820,8 @@ void tst_QQuickGridView::removed_basic()
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
}
// Remove first item (which is the current item);
@@ -836,8 +841,8 @@ void tst_QQuickGridView::removed_basic()
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
}
// Remove items not visible
@@ -849,8 +854,8 @@ void tst_QQuickGridView::removed_basic()
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
}
// Remove items before visible
@@ -867,8 +872,8 @@ void tst_QQuickGridView::removed_basic()
for (int i = 6; i < 18; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
}
// Remove currentIndex
@@ -886,8 +891,8 @@ void tst_QQuickGridView::removed_basic()
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
}
// remove item outside current view.
@@ -895,7 +900,7 @@ void tst_QQuickGridView::removed_basic()
gridview->setContentY(240);
model.removeItem(30);
- QTRY_VERIFY(gridview->currentIndex() == 31);
+ QTRY_COMPARE(gridview->currentIndex(), 31);
// remove current item beyond visible items.
gridview->setCurrentIndex(20);
@@ -912,7 +917,7 @@ void tst_QQuickGridView::removed_basic()
model.removeItem(6);
QTRY_COMPARE(gridview->currentIndex(), 7);
- QTRY_VERIFY(gridview->currentItem() == oldCurrent);
+ QTRY_COMPARE(gridview->currentItem(), oldCurrent);
delete window;
}
@@ -1211,7 +1216,7 @@ void tst_QQuickGridView::addOrRemoveBeforeVisible()
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", i));
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
QTRY_VERIFY(item->y() == (i/3)*60 + newTopContentY);
}
@@ -1249,10 +1254,10 @@ void tst_QQuickGridView::clear()
model.clear();
gridview->forceLayout();
- QVERIFY(gridview->count() == 0);
- QVERIFY(gridview->currentItem() == 0);
- QVERIFY(gridview->contentY() == 0);
- QVERIFY(gridview->currentIndex() == -1);
+ QCOMPARE(gridview->count(), 0);
+ QVERIFY(!gridview->currentItem());
+ QCOMPARE(gridview->contentY(), qreal(0));
+ QCOMPARE(gridview->currentIndex(), -1);
QCOMPARE(gridview->contentHeight(), 0.0);
// confirm sanity when adding an item to cleared list
@@ -1260,7 +1265,7 @@ void tst_QQuickGridView::clear()
gridview->forceLayout();
QTRY_COMPARE(gridview->count(), 1);
QVERIFY(gridview->currentItem() != 0);
- QVERIFY(gridview->currentIndex() == 0);
+ QCOMPARE(gridview->currentIndex(), 0);
delete window;
}
@@ -1799,7 +1804,7 @@ void tst_QQuickGridView::swapWithFirstItem()
// ensure content position is stable
gridview->setContentY(0);
model.moveItem(10, 0);
- QTRY_VERIFY(gridview->contentY() == 0);
+ QTRY_COMPARE(gridview->contentY(), qreal(0));
delete window;
}
@@ -1849,7 +1854,7 @@ void tst_QQuickGridView::currentIndex()
gridview->setCurrentIndex(35);
QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
gridview->setCurrentIndex(0);
- QTRY_VERIFY(gridview->verticalVelocity() == 0.0);
+ QTRY_COMPARE(gridview->verticalVelocity(), 0.0);
// footer should become visible if it is out of view, and then current index moves to the first row
window->rootObject()->setProperty("showFooter", true);
@@ -1871,7 +1876,7 @@ void tst_QQuickGridView::currentIndex()
// turn off auto highlight
gridview->setHighlightFollowsCurrentItem(false);
- QVERIFY(gridview->highlightFollowsCurrentItem() == false);
+ QVERIFY(!gridview->highlightFollowsCurrentItem());
QVERIFY(gridview->highlightItem());
qreal hlPosX = gridview->highlightItem()->x();
qreal hlPosY = gridview->highlightItem()->y();
@@ -1971,7 +1976,7 @@ void tst_QQuickGridView::keyNavigation()
window->requestActivate();
QTest::qWaitForWindowActive(window);
- QTRY_VERIFY(qGuiApp->focusWindow() == window);
+ QTRY_COMPARE(qGuiApp->focusWindow(), window);
QCOMPARE(gridview->currentIndex(), 0);
QTest::keyClick(window, forwardsKey);
@@ -2256,15 +2261,15 @@ void tst_QQuickGridView::defaultValues()
QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
QTRY_VERIFY(obj != 0);
- QTRY_VERIFY(obj->model() == QVariant());
- QTRY_VERIFY(obj->delegate() == 0);
+ QTRY_COMPARE(obj->model(), QVariant());
+ QTRY_VERIFY(!obj->delegate());
QTRY_COMPARE(obj->currentIndex(), -1);
- QTRY_VERIFY(obj->currentItem() == 0);
+ QTRY_VERIFY(!obj->currentItem());
QTRY_COMPARE(obj->count(), 0);
- QTRY_VERIFY(obj->highlight() == 0);
- QTRY_VERIFY(obj->highlightItem() == 0);
+ QTRY_VERIFY(!obj->highlight());
+ QTRY_VERIFY(!obj->highlightItem());
QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
- QTRY_VERIFY(obj->flow() == 0);
+ QTRY_COMPARE(obj->flow(), QQuickGridView::FlowLeftToRight);
QTRY_COMPARE(obj->isWrapEnabled(), false);
#ifdef QML_VIEW_DEFAULTCACHEBUFFER
QTRY_COMPARE(obj->cacheBuffer(), QML_VIEW_DEFAULTCACHEBUFFER);
@@ -2291,7 +2296,7 @@ void tst_QQuickGridView::properties()
QTRY_VERIFY(obj->highlight() != 0);
QTRY_VERIFY(obj->highlightItem() != 0);
QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
- QTRY_VERIFY(obj->flow() == 0);
+ QTRY_COMPARE(obj->flow(), QQuickGridView::FlowLeftToRight);
QTRY_COMPARE(obj->isWrapEnabled(), true);
QTRY_COMPARE(obj->cacheBuffer(), 200);
QTRY_COMPARE(obj->cellWidth(), qreal(100));
@@ -2728,7 +2733,7 @@ void tst_QQuickGridView::mirroring()
foreach (const QString objectName, objectNames)
QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
- QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
+ QCOMPARE(gridviewB->layoutDirection(), gridviewB->effectiveLayoutDirection());
QQuickItemPrivate::get(gridviewB)->setLayoutMirror(true);
QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
@@ -3016,7 +3021,7 @@ void tst_QQuickGridView::footer()
QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
QVERIFY(footer);
- QVERIFY(footer == gridview->footerItem());
+ QCOMPARE(footer, gridview->footerItem());
QCOMPARE(footer->position(), initialFooterPos);
QCOMPARE(footer->width(), 100.);
@@ -3082,7 +3087,7 @@ void tst_QQuickGridView::footer()
QVERIFY(!footer);
footer = findItem<QQuickText>(contentItem, "footer2");
QVERIFY(footer);
- QVERIFY(footer == gridview->footerItem());
+ QCOMPARE(footer, gridview->footerItem());
QCOMPARE(footer->position(), changedFooterPos);
QCOMPARE(footer->width(), 50.);
@@ -3265,7 +3270,7 @@ void tst_QQuickGridView::header()
QQuickText *header = findItem<QQuickText>(contentItem, "header");
QVERIFY(header);
- QVERIFY(header == gridview->headerItem());
+ QCOMPARE(header, gridview->headerItem());
QCOMPARE(header->position(), initialHeaderPos);
QCOMPARE(header->width(), 100.);
@@ -3302,7 +3307,7 @@ void tst_QQuickGridView::header()
header = findItem<QQuickText>(contentItem, "header2");
QVERIFY(header);
- QVERIFY(header == gridview->headerItem());
+ QCOMPARE(header, gridview->headerItem());
QCOMPARE(header->position(), changedHeaderPos);
QCOMPARE(header->width(), 50.);
@@ -3609,11 +3614,11 @@ void tst_QQuickGridView::resetModel_headerFooter()
// A reset should not force a new header or footer to be created.
QQuickItem *newHeader = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(newHeader == header);
+ QCOMPARE(newHeader, header);
QCOMPARE(header->y(), -header->height());
QQuickItem *newFooter = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(newFooter == footer);
+ QCOMPARE(newFooter, footer);
QCOMPARE(footer->y(), 60.*2);
delete window;
@@ -4315,8 +4320,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);
@@ -5810,7 +5826,7 @@ void tst_QQuickGridView::cacheBuffer()
window->engine()->setIncubationController(&controller);
window->rootObject()->setProperty("cacheBuffer", 200);
- QTRY_VERIFY(gridview->cacheBuffer() == 200);
+ QTRY_COMPARE(gridview->cacheBuffer(), 200);
// items will be created one at a time
for (int i = itemCount; i < qMin(itemCount+9,model.count()); ++i) {
@@ -5910,8 +5926,8 @@ void tst_QQuickGridView::asynchronous()
for (int i = 0; i < 12; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QVERIFY(item->x() == (i%3)*100);
- QVERIFY(item->y() == (i/3)*100);
+ QCOMPARE(item->x(), qreal((i%3)*100));
+ QCOMPARE(item->y(), qreal((i/3)*100));
}
delete window;
@@ -6329,7 +6345,7 @@ void tst_QQuickGridView::matchIndexLists(const QVariantList &indexLists, const Q
void tst_QQuickGridView::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes)
{
for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) {
- QVERIFY(it.value().type() == QVariant::Int);
+ QCOMPARE(it.value().type(), QVariant::Int);
QString name = it.key();
int itemIndex = it.value().toInt();
QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
@@ -6460,6 +6476,93 @@ 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;
+}
+
+void tst_QQuickGridView::QTBUG_45640()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("qtbug45640.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
+ QVERIFY(gridview != 0);
+
+ QCOMPARE(gridview->contentY(), qreal(-50.0));
+
+ gridview->moveCurrentIndexDown();
+
+ QTRY_VERIFY(gridview->contentY() > qreal(-50.0) && gridview->contentY() < qreal(0.0));
+
+ 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..71e9d747f4 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -121,7 +121,7 @@ void tst_qquickimage::noSource()
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
QVERIFY(obj != 0);
QCOMPARE(obj->source(), QUrl());
- QVERIFY(obj->status() == QQuickImage::Null);
+ QCOMPARE(obj->status(), QQuickImage::Null);
QCOMPARE(obj->width(), 0.);
QCOMPARE(obj->height(), 0.);
QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
@@ -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()));
@@ -189,28 +201,28 @@ void tst_qquickimage::imageSource()
QVERIFY(obj != 0);
if (async)
- QVERIFY(obj->asynchronous() == true);
+ QVERIFY(obj->asynchronous());
else
- QVERIFY(obj->asynchronous() == false);
+ QVERIFY(!obj->asynchronous());
if (cache)
- QVERIFY(obj->cache() == true);
+ QVERIFY(obj->cache());
else
- QVERIFY(obj->cache() == false);
+ QVERIFY(!obj->cache());
if (remote || async)
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
+ QTRY_COMPARE(obj->status(), QQuickImage::Loading);
QCOMPARE(obj->source(), remote ? source : QUrl(source));
if (error.isEmpty()) {
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
QCOMPARE(obj->width(), qreal(width));
QCOMPARE(obj->height(), qreal(height));
QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
QCOMPARE(obj->progress(), 1.0);
} else {
- QTRY_VERIFY(obj->status() == QQuickImage::Error);
+ QTRY_COMPARE(obj->status(), QQuickImage::Error);
}
delete obj;
@@ -225,14 +237,14 @@ void tst_qquickimage::clearSource()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickImage::Ready);
+ QCOMPARE(obj->status(), QQuickImage::Ready);
QCOMPARE(obj->width(), 120.);
QCOMPARE(obj->height(), 120.);
QCOMPARE(obj->progress(), 1.0);
ctxt->setContextProperty("srcImage", "");
QVERIFY(obj->source().isEmpty());
- QVERIFY(obj->status() == QQuickImage::Null);
+ QCOMPARE(obj->status(), QQuickImage::Null);
QCOMPARE(obj->width(), 0.);
QCOMPARE(obj->height(), 0.);
QCOMPARE(obj->progress(), 0.0);
@@ -533,7 +545,7 @@ void tst_qquickimage::noLoading()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickImage::Ready);
+ QCOMPARE(obj->status(), QQuickImage::Ready);
QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(QUrl)));
QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
@@ -541,29 +553,30 @@ void tst_qquickimage::noLoading()
// Loading local file
ctxt->setContextProperty("srcImage", testFileUrl("green.png"));
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 1);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 1);
// Loading remote file
ctxt->setContextProperty("srcImage", server.url("/rect.png"));
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
- QTRY_VERIFY(obj->progress() == 0.0);
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Loading);
+ QTRY_COMPARE(obj->progress(), 0.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(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(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(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;
@@ -615,7 +628,7 @@ void tst_qquickimage::sourceSize_QTBUG_14303()
QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
QTRY_VERIFY(obj != 0);
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->sourceSize().width(), 200);
QTRY_COMPARE(obj->sourceSize().height(), 200);
@@ -831,8 +844,8 @@ void tst_qquickimage::progressAndStatusChanges()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QCOMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
qRegisterMetaType<QQuickImageBase::Status>();
QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(QUrl)));
@@ -841,33 +854,33 @@ void tst_qquickimage::progressAndStatusChanges()
// Same image
ctxt->setContextProperty("srcImage", testFileUrl("heart.png"));
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 0);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 0);
// Loading local file
ctxt->setContextProperty("srcImage", testFileUrl("colors.png"));
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 1);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 1);
// Loading remote file
ctxt->setContextProperty("srcImage", server.url("/heart.png"));
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
- QTRY_VERIFY(obj->progress() == 0.0);
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Loading);
+ QTRY_COMPARE(obj->progress(), 0.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
+ QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 2);
QTRY_VERIFY(progressSpy.count() > 1);
QTRY_COMPARE(statusSpy.count(), 3);
ctxt->setContextProperty("srcImage", "");
- QTRY_VERIFY(obj->status() == QQuickImage::Null);
- QTRY_VERIFY(obj->progress() == 0.0);
+ QTRY_COMPARE(obj->status(), QQuickImage::Null);
+ QTRY_COMPARE(obj->progress(), 0.0);
QTRY_COMPARE(sourceSpy.count(), 3);
QTRY_VERIFY(progressSpy.count() > 2);
QTRY_COMPARE(statusSpy.count(), 4);
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index dae46b5c3d..644f2be129 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);
@@ -234,15 +237,15 @@ void tst_qquickimageprovider::runTest(bool async, QQuickImageProvider *provider)
async |= (provider->flags() & QQuickImageProvider::ForceAsynchronousImageLoading) != 0;
if (async)
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
+ QTRY_COMPARE(obj->status(), QQuickImage::Loading);
QCOMPARE(obj->source(), QUrl(source));
if (error.isEmpty()) {
if (async)
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_COMPARE(obj->status(), QQuickImage::Ready);
else
- QVERIFY(obj->status() == QQuickImage::Ready);
+ QCOMPARE(obj->status(), QQuickImage::Ready);
if (QByteArray(QTest::currentDataTag()).startsWith("qimage"))
QCOMPARE(static_cast<TestQImageProvider*>(provider)->lastImageId, imageId);
else
@@ -254,9 +257,9 @@ void tst_qquickimageprovider::runTest(bool async, QQuickImageProvider *provider)
QCOMPARE(obj->progress(), 1.0);
} else {
if (async)
- QTRY_VERIFY(obj->status() == QQuickImage::Error);
+ QTRY_COMPARE(obj->status(), QQuickImage::Error);
else
- QVERIFY(obj->status() == QQuickImage::Error);
+ QCOMPARE(obj->status(), QQuickImage::Error);
}
delete obj;
@@ -453,7 +456,102 @@ void tst_qquickimageprovider::threadTest()
provider->cond.wakeAll();
QTest::qWait(250);
foreach (QQuickImage *img, images) {
- QTRY_VERIFY(img->status() == QQuickImage::Ready);
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ }
+}
+
+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_COMPARE(provider->pool.activeThreadCount(), 4);
+ foreach (QQuickImage *img, images) {
+ QTRY_COMPARE(img->status(), QQuickImage::Loading);
+ }
+ provider->ok = true;
+ provider->condition.wakeAll();
+ foreach (QQuickImage *img, images) {
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
}
}
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/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index c79af91747..73e691b08c 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -276,7 +276,7 @@ void tst_qquickitem::simpleFocus()
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *l1c1 = new TestItem(window.contentItem());
QQuickItem *l1c2 = new TestItem(window.contentItem());
@@ -327,7 +327,7 @@ void tst_qquickitem::scopedFocus()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *l1c1 = new TestItem(window.contentItem());
QQuickItem *l1c2 = new TestItem(window.contentItem());
@@ -407,7 +407,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *item = new TestItem;
@@ -427,7 +427,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *item = new TestItem(window.contentItem());
@@ -456,7 +456,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *tree = new TestItem;
QQuickItem *c1 = new TestItem(tree);
@@ -480,7 +480,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *tree = new TestFocusScope;
QQuickItem *c1 = new TestItem(tree);
QQuickItem *c2 = new TestItem(tree);
@@ -508,7 +508,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *tree = new TestFocusScope;
QQuickItem *c1 = new TestItem(tree);
QQuickItem *c2 = new TestItem(tree);
@@ -534,7 +534,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *tree = new TestFocusScope;
QQuickItem *c1 = new TestItem(tree);
@@ -574,7 +574,7 @@ void tst_qquickitem::changeParent()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
FocusState focusState;
@@ -596,7 +596,7 @@ void tst_qquickitem::changeParent()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestItem(window.contentItem());
@@ -617,7 +617,7 @@ void tst_qquickitem::changeParent()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestFocusScope(window.contentItem());
QQuickItem *item = new TestItem(child);
@@ -639,7 +639,7 @@ void tst_qquickitem::changeParent()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestFocusScope(window.contentItem());
QQuickItem *item = new TestItem(child2);
@@ -661,7 +661,7 @@ void tst_qquickitem::changeParent()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestFocusScope(window.contentItem());
QQuickItem *item = new TestItem(child2);
@@ -687,7 +687,7 @@ void tst_qquickitem::changeParent()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *item = new TestFocusScope(window.contentItem());
QQuickItem *child = new TestItem(item);
QQuickItem *child2 = new TestItem;
@@ -726,7 +726,7 @@ void tst_qquickitem::multipleFocusClears()
view.setSource(testFileUrl("multipleFocusClears.qml"));
view.show();
ensureFocus(&view);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &view);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &view);
}
void tst_qquickitem::focusSubItemInNonFocusScope()
@@ -757,7 +757,7 @@ void tst_qquickitem::parentItemWithFocus()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
{
QQuickItem parent;
QQuickItem child;
@@ -856,7 +856,7 @@ void tst_qquickitem::reparentFocusedItem()
{
QQuickWindow window;
ensureFocus(&window);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem parent(window.contentItem());
QQuickItem child(&parent);
@@ -883,18 +883,18 @@ void tst_qquickitem::reparentFocusedItem()
void tst_qquickitem::constructor()
{
QScopedPointer<QQuickItem> root(new QQuickItem);
- QVERIFY(root->parent() == 0);
- QVERIFY(root->parentItem() == 0);
+ QVERIFY(!root->parent());
+ QVERIFY(!root->parentItem());
QQuickItem *child1 = new QQuickItem(root.data());
- QVERIFY(child1->parent() == root.data());
- QVERIFY(child1->parentItem() == root.data());
+ QCOMPARE(child1->parent(), root.data());
+ QCOMPARE(child1->parentItem(), root.data());
QCOMPARE(root->childItems().count(), 1);
QCOMPARE(root->childItems().at(0), child1);
QQuickItem *child2 = new QQuickItem(root.data());
- QVERIFY(child2->parent() == root.data());
- QVERIFY(child2->parentItem() == root.data());
+ QCOMPARE(child2->parent(), root.data());
+ QCOMPARE(child2->parentItem(), root.data());
QCOMPARE(root->childItems().count(), 2);
QCOMPARE(root->childItems().at(0), child1);
QCOMPARE(root->childItems().at(1), child2);
@@ -903,41 +903,41 @@ void tst_qquickitem::constructor()
void tst_qquickitem::setParentItem()
{
QQuickItem *root = new QQuickItem;
- QVERIFY(root->parent() == 0);
- QVERIFY(root->parentItem() == 0);
+ QVERIFY(!root->parent());
+ QVERIFY(!root->parentItem());
QQuickItem *child1 = new QQuickItem;
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == 0);
+ QVERIFY(!child1->parent());
+ QVERIFY(!child1->parentItem());
child1->setParentItem(root);
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == root);
+ QVERIFY(!child1->parent());
+ QCOMPARE(child1->parentItem(), root);
QCOMPARE(root->childItems().count(), 1);
QCOMPARE(root->childItems().at(0), child1);
QQuickItem *child2 = new QQuickItem;
- QVERIFY(child2->parent() == 0);
- QVERIFY(child2->parentItem() == 0);
+ QVERIFY(!child2->parent());
+ QVERIFY(!child2->parentItem());
child2->setParentItem(root);
- QVERIFY(child2->parent() == 0);
- QVERIFY(child2->parentItem() == root);
+ QVERIFY(!child2->parent());
+ QCOMPARE(child2->parentItem(), root);
QCOMPARE(root->childItems().count(), 2);
QCOMPARE(root->childItems().at(0), child1);
QCOMPARE(root->childItems().at(1), child2);
child1->setParentItem(0);
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == 0);
+ QVERIFY(!child1->parent());
+ QVERIFY(!child1->parentItem());
QCOMPARE(root->childItems().count(), 1);
QCOMPARE(root->childItems().at(0), child2);
delete root;
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == 0);
- QVERIFY(child2->parent() == 0);
- QVERIFY(child2->parentItem() == 0);
+ QVERIFY(!child1->parent());
+ QVERIFY(!child1->parentItem());
+ QVERIFY(!child2->parent());
+ QVERIFY(!child2->parentItem());
delete child1;
delete child2;
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 69c7250134..396f183860 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -319,7 +319,7 @@ void tst_QQuickItem::activeFocusOnTab()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
// original: button12
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button12");
@@ -431,7 +431,7 @@ void tst_QQuickItem::activeFocusOnTab2()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
// original: button12
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button12");
@@ -471,7 +471,7 @@ void tst_QQuickItem::activeFocusOnTab3()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
// original: button1
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button1");
@@ -653,7 +653,7 @@ void tst_QQuickItem::activeFocusOnTab4()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
// original: button11
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button11");
@@ -685,7 +685,7 @@ void tst_QQuickItem::activeFocusOnTab5()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
// original: button11 in sub1
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button11");
@@ -719,7 +719,7 @@ void tst_QQuickItem::activeFocusOnTab6()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
// original: button12
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button12");
@@ -777,7 +777,7 @@ void tst_QQuickItem::activeFocusOnTab7()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button1");
QVERIFY(item);
@@ -810,7 +810,7 @@ void tst_QQuickItem::activeFocusOnTab8()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *content = window->contentItem();
QVERIFY(content);
@@ -862,7 +862,7 @@ void tst_QQuickItem::activeFocusOnTab9()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *content = window->contentItem();
QVERIFY(content);
@@ -913,7 +913,7 @@ void tst_QQuickItem::activeFocusOnTab10()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *content = window->contentItem();
QVERIFY(content);
@@ -996,7 +996,7 @@ void tst_QQuickItem::nextItemInFocusChain()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *button11 = findItem<QQuickItem>(window->rootObject(), "button11");
QVERIFY(button11);
@@ -1072,7 +1072,7 @@ void tst_QQuickItem::nextItemInFocusChain2()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *button11 = findItem<QQuickItem>(window->rootObject(), "button11");
QVERIFY(button11);
@@ -1117,7 +1117,7 @@ void tst_QQuickItem::nextItemInFocusChain3()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
}
void tst_QQuickItem::keys()
@@ -1135,7 +1135,7 @@ void tst_QQuickItem::keys()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QVERIFY(window->rootObject());
QCOMPARE(window->rootObject()->property("isEnabled").toBool(), true);
@@ -1145,7 +1145,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_A));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(!key.isAccepted());
testObject->reset();
@@ -1155,7 +1155,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_A));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::ShiftModifier));
QVERIFY(key.isAccepted());
testObject->reset();
@@ -1165,7 +1165,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_Return));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
QCOMPARE(testObject->mText, QLatin1String("Return"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(key.isAccepted());
testObject->reset();
@@ -1175,7 +1175,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_0));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_0));
QCOMPARE(testObject->mText, QLatin1String("0"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(key.isAccepted());
testObject->reset();
@@ -1185,7 +1185,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_9));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_9));
QCOMPARE(testObject->mText, QLatin1String("9"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(!key.isAccepted());
testObject->reset();
@@ -1195,7 +1195,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_Tab));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Tab));
QCOMPARE(testObject->mText, QLatin1String("Tab"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(key.isAccepted());
testObject->reset();
@@ -1205,7 +1205,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_Backtab));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Backtab));
QCOMPARE(testObject->mText, QLatin1String("Backtab"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(key.isAccepted());
testObject->reset();
@@ -1214,8 +1214,8 @@ void tst_QQuickItem::keys()
QGuiApplication::sendEvent(window, &key);
QCOMPARE(testObject->mKey, int(Qt::Key_VolumeUp));
QCOMPARE(testObject->mForwardedKey, int(Qt::Key_VolumeUp));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(testObject->mNativeScanCode == 1234);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
+ QCOMPARE(testObject->mNativeScanCode, quint32(1234));
QVERIFY(key.isAccepted());
testObject->reset();
@@ -1226,7 +1226,7 @@ void tst_QQuickItem::keys()
QCOMPARE(testObject->mKey, int(Qt::Key_A));
QCOMPARE(testObject->mForwardedKey, 0);
QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(!key.isAccepted());
testObject->reset();
@@ -1321,7 +1321,7 @@ void tst_QQuickItem::keysProcessingOrder()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
KeyTestItem *testItem = qobject_cast<KeyTestItem*>(window->rootObject());
QVERIFY(testItem);
@@ -1332,7 +1332,7 @@ void tst_QQuickItem::keysProcessingOrder()
QGuiApplication::sendEvent(window, &key);
QCOMPARE(testObject->mKey, int(Qt::Key_A));
QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(key.isAccepted());
testObject->reset();
@@ -1352,7 +1352,7 @@ void tst_QQuickItem::keysProcessingOrder()
QGuiApplication::sendEvent(window, &key);
QCOMPARE(testObject->mKey, int(Qt::Key_B));
QCOMPARE(testObject->mText, QLatin1String("B"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QCOMPARE(testObject->mModifiers, int(Qt::NoModifier));
QVERIFY(!key.isAccepted());
testObject->reset();
@@ -1379,7 +1379,7 @@ void tst_QQuickItem::keysim()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QVERIFY(window->rootObject());
QVERIFY(window->rootObject()->hasFocus() && window->rootObject()->hasActiveFocus());
@@ -1405,7 +1405,7 @@ void tst_QQuickItem::keysForward()
window.show();
window.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(QGuiApplication::focusWindow() == &window);
+ QCOMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *rootItem = qobject_cast<QQuickItem *>(window.rootObject());
QVERIFY(rootItem);
@@ -1645,7 +1645,7 @@ void tst_QQuickItem::keyNavigation()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
QVERIFY(item);
@@ -1722,7 +1722,7 @@ void tst_QQuickItem::keyNavigation_RightToLeft()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
QVERIFY(rootItem);
@@ -1777,7 +1777,7 @@ void tst_QQuickItem::keyNavigation_skipNotVisible()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
QVERIFY(item);
@@ -1852,7 +1852,7 @@ void tst_QQuickItem::keyNavigation_implicitSetting()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QEvent wa(QEvent::WindowActivate);
QGuiApplication::sendEvent(window, &wa);
@@ -1982,7 +1982,7 @@ void tst_QQuickItem::keyNavigation_focusReason()
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
// install event filter on first item
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
@@ -2040,8 +2040,8 @@ void tst_QQuickItem::smooth()
QVERIFY(item->smooth());
QCOMPARE(spy.count(),1);
QList<QVariant> arguments = spy.first();
- QVERIFY(arguments.count() == 1);
- QVERIFY(arguments.at(0).toBool() == true);
+ QCOMPARE(arguments.count(), 1);
+ QVERIFY(arguments.at(0).toBool());
item->setSmooth(true);
QCOMPARE(spy.count(),1);
@@ -2069,8 +2069,8 @@ void tst_QQuickItem::antialiasing()
QVERIFY(item->antialiasing());
QCOMPARE(spy.count(),1);
QList<QVariant> arguments = spy.first();
- QVERIFY(arguments.count() == 1);
- QVERIFY(arguments.at(0).toBool() == true);
+ QCOMPARE(arguments.count(), 1);
+ QVERIFY(arguments.at(0).toBool());
item->setAntialiasing(true);
QCOMPARE(spy.count(),1);
@@ -2098,8 +2098,8 @@ void tst_QQuickItem::clip()
QVERIFY(item->clip());
QList<QVariant> arguments = spy.first();
- QVERIFY(arguments.count() == 1);
- QVERIFY(arguments.at(0).toBool() == true);
+ QCOMPARE(arguments.count(), 1);
+ QVERIFY(arguments.at(0).toBool());
QCOMPARE(spy.count(),1);
item->setClip(true);
@@ -2325,7 +2325,7 @@ void tst_QQuickItem::propertyChanges()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item");
QQuickItem *parentItem = findItem<QQuickItem>(window->rootObject(), "parentItem");
@@ -2353,7 +2353,7 @@ void tst_QQuickItem::propertyChanges()
QCOMPARE(item->parentItem(), parentItem);
QCOMPARE(parentSpy.count(),1);
QList<QVariant> parentArguments = parentSpy.first();
- QVERIFY(parentArguments.count() == 1);
+ QCOMPARE(parentArguments.count(), 1);
QCOMPARE(item->parentItem(), qvariant_cast<QQuickItem *>(parentArguments.at(0)));
QCOMPARE(childrenChangedSpy.count(),1);
@@ -2369,19 +2369,19 @@ void tst_QQuickItem::propertyChanges()
QCOMPARE(item->baselineOffset(), 10.0);
QCOMPARE(baselineOffsetSpy.count(),1);
QList<QVariant> baselineOffsetArguments = baselineOffsetSpy.first();
- QVERIFY(baselineOffsetArguments.count() == 1);
+ QCOMPARE(baselineOffsetArguments.count(), 1);
QCOMPARE(item->baselineOffset(), baselineOffsetArguments.at(0).toReal());
QCOMPARE(parentItem->childrenRect(), QRectF(0.0,0.0,100.0,200.0));
QCOMPARE(childrenRectSpy.count(),1);
QList<QVariant> childrenRectArguments = childrenRectSpy.at(0);
- QVERIFY(childrenRectArguments.count() == 1);
+ QCOMPARE(childrenRectArguments.count(), 1);
QCOMPARE(parentItem->childrenRect(), childrenRectArguments.at(0).toRectF());
QCOMPARE(item->hasActiveFocus(), true);
QCOMPARE(focusSpy.count(),1);
QList<QVariant> focusArguments = focusSpy.first();
- QVERIFY(focusArguments.count() == 1);
+ QCOMPARE(focusArguments.count(), 1);
QCOMPARE(focusArguments.at(0).toBool(), true);
QCOMPARE(parentItem->hasActiveFocus(), false);
@@ -2737,7 +2737,7 @@ void tst_QQuickItem::contains()
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(QGuiApplication::focusWindow() == window);
+ QCOMPARE(QGuiApplication::focusWindow(), window);
QQuickItem *root = qobject_cast<QQuickItem *>(window->rootObject());
QVERIFY(root);
diff --git a/tests/auto/quick/qquickitemlayer/data/TextureMirroring.qml b/tests/auto/quick/qquickitemlayer/data/TextureMirroring.qml
new file mode 100644
index 0000000000..2827960153
--- /dev/null
+++ b/tests/auto/quick/qquickitemlayer/data/TextureMirroring.qml
@@ -0,0 +1,159 @@
+import QtQuick 2.6
+
+Item
+{
+ width: 250
+ height: 50
+
+ property int mirroring: 0
+
+ // Layered box without effect. Mirroring should not affect how it looks.
+ Rectangle {
+ x: 0
+ y: 0
+ width: 50
+ height: 50
+ layer.enabled: true
+ layer.textureMirroring: mirroring
+ Rectangle {
+ x: 0
+ y: 0
+ width: 25
+ height: 25
+ color: "#000000"
+ }
+ Rectangle {
+ x: 25
+ y: 0
+ width: 25
+ height: 25
+ color: "#ff0000"
+ }
+ Rectangle {
+ x: 0
+ y: 25
+ width: 25
+ height: 25
+ color: "#00ff00"
+ }
+ Rectangle {
+ x: 25
+ y: 25
+ width: 25
+ height: 25
+ color: "#0000ff"
+ }
+ }
+
+ // Layered box with effect. Mirroring should affect how it looks.
+ Rectangle {
+ id: layeredEffectBox
+ x: 50
+ y: 0
+ width: 50
+ height: 50
+ layer.enabled: true
+ layer.textureMirroring: mirroring
+ layer.samplerName: "source"
+ layer.effect: ShaderEffect {
+ property variant source: layeredEffectBox
+ fragmentShader: "
+ uniform lowp sampler2D source;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ gl_FragColor = texture2D(source, qt_TexCoord0);
+ }"
+
+ }
+
+ Rectangle {
+ x: 0
+ y: 0
+ width: 25
+ height: 25
+ color: "#000000"
+ }
+ Rectangle {
+ x: 25
+ y: 0
+ width: 25
+ height: 25
+ color: "#ff0000"
+ }
+ Rectangle {
+ x: 0
+ y: 25
+ width: 25
+ height: 25
+ color: "#00ff00"
+ }
+ Rectangle {
+ x: 25
+ y: 25
+ width: 25
+ height: 25
+ color: "#0000ff"
+ }
+ }
+
+ // Non-layered source item for ShaderEffectSource. Mirroring should not affect how it looks.
+ Rectangle {
+ id: box2
+ x: 100
+ y: 0
+ width: 50
+ height: 50
+ Rectangle {
+ x: 0
+ y: 0
+ width: 25
+ height: 25
+ color: "#000000"
+ }
+ Rectangle {
+ x: 25
+ y: 0
+ width: 25
+ height: 25
+ color: "#ff0000"
+ }
+ Rectangle {
+ x: 0
+ y: 25
+ width: 25
+ height: 25
+ color: "#00ff00"
+ }
+ Rectangle {
+ x: 25
+ y: 25
+ width: 25
+ height: 25
+ color: "#0000ff"
+ }
+ }
+ // ShaderEffectSource item. Mirroring should not affect how it looks.
+ ShaderEffectSource {
+ id: theSource
+ x: 150
+ y: 0
+ width: 50
+ height: 50
+ sourceItem: box2
+ textureMirroring: mirroring
+ }
+ // ShaderEffect item. Mirroring should affect how it looks.
+ ShaderEffect {
+ x: 200
+ y: 0
+ width: 50
+ height: 50
+ property variant source: theSource
+ fragmentShader: "
+ uniform lowp sampler2D source;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ gl_FragColor = texture2D(source, qt_TexCoord0);
+ }"
+ }
+}
diff --git a/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro b/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro
index 999f0cf23d..a087948f6d 100644
--- a/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro
+++ b/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro
@@ -25,5 +25,6 @@ OTHER_FILES += \
data/DisableLayer.qml \
data/SamplerNameChange.qml \
data/ItemEffect.qml \
- data/RectangleEffect.qml
+ data/RectangleEffect.qml \
+ data/TextureMirroring.qml
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
index 25a75c0580..094b69c07f 100644
--- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
+++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
@@ -87,7 +87,12 @@ private slots:
void itemEffect();
void rectangleEffect();
+ void textureMirroring_data();
+ void textureMirroring();
+
private:
+ void mirroringCheck(int mirroring, int x, bool shouldMirror, const QImage &fb);
+
bool m_isMesaSoftwareRasterizer;
int m_mesaVersion;
};
@@ -434,6 +439,94 @@ void tst_QQuickItemLayer::rectangleEffect()
QCOMPARE(fb.pixel(0, 100), qRgb(0, 0, 0xff));
}
+void tst_QQuickItemLayer::textureMirroring_data()
+{
+ QTest::addColumn<int>("mirroring");
+
+ QTest::newRow("no mirroring") << 0;
+ QTest::newRow("horizontal") << 1;
+ QTest::newRow("vertical") << 2;
+ QTest::newRow("horizontal | vertical") << 3;
+}
+
+void tst_QQuickItemLayer::textureMirroring()
+{
+ QFETCH(int, mirroring);
+
+ QQuickView view;
+ view.setSource(testFileUrl("TextureMirroring.qml"));
+
+ QQuickItem *child = view.contentItem()->childItems().at(0);
+ child->setProperty("mirroring", mirroring);
+
+ view.show();
+
+ QTest::qWaitForWindowExposed(&view);
+
+ QImage fb = view.grabWindow();
+
+ // Mirroring should have no visual effect on layered item without shader effect
+ mirroringCheck(mirroring, 0, false, fb);
+
+ // Mirroring should have visual effect on layered item with shader effect
+ mirroringCheck(mirroring, 50, true, fb);
+
+ // Mirroring should have no visual effect on source item for ShaderEffectSource
+ mirroringCheck(mirroring, 100, false, fb);
+
+ // Mirroring should have no visual effect on ShaderEffectSource item
+ mirroringCheck(mirroring, 150, false, fb);
+
+ // Mirroring should have visual effect on ShaderEffect item itself
+ mirroringCheck(mirroring, 200, true, fb);
+}
+
+void tst_QQuickItemLayer::mirroringCheck(int mirroring, int x, bool shouldMirror, const QImage &fb)
+{
+ int offset = 10;
+ int spacing = 25;
+
+ if (shouldMirror) {
+ switch (mirroring) {
+ case 0: { // No mirroring -> Visually Y gets swapped, X is default
+ QCOMPARE(fb.pixel(x + offset, offset), qRgb(0, 0xff, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset), qRgb(0, 0, 0xff));
+ QCOMPARE(fb.pixel(x + offset, offset + spacing), qRgb(0, 0, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset + spacing), qRgb(0xff, 0, 0));
+ break;
+ }
+ case 1: { // Horizontal mirroring -> Visually both X and Y get swapped, as neither is default
+ QCOMPARE(fb.pixel(x + offset, offset), qRgb(0, 0, 0xff));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset), qRgb(0, 0xff, 0));
+ QCOMPARE(fb.pixel(x + offset, offset + spacing), qRgb(0xff, 0, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset + spacing), qRgb(0, 0, 0));
+ break;
+ }
+ case 2: { // Vertical mirroring -> The default case, nothing gets swapped
+ QCOMPARE(fb.pixel(x + offset, offset), qRgb(0, 0, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset), qRgb(0xff, 0, 0));
+ QCOMPARE(fb.pixel(x + offset, offset + spacing), qRgb(0, 0xff, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset + spacing), qRgb(0, 0, 0xff));
+ break;
+ }
+ case 3: { // Both axes mirrored -> Visually X gets swapped, Y is default
+ QCOMPARE(fb.pixel(x + offset, offset), qRgb(0xff, 0, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset), qRgb(0, 0, 0));
+ QCOMPARE(fb.pixel(x + offset, offset + spacing), qRgb(0, 0, 0xff));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset + spacing), qRgb(0, 0xff, 0));
+ break;
+ }
+ default:
+ qWarning() << "Invalid case!";
+ break;
+ }
+ } else {
+ QCOMPARE(fb.pixel(x + offset, offset), qRgb(0, 0, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset), qRgb(0xff, 0, 0));
+ QCOMPARE(fb.pixel(x + offset, offset + spacing), qRgb(0, 0xff, 0));
+ QCOMPARE(fb.pixel(x + offset + spacing, offset + spacing), qRgb(0, 0, 0xff));
+ }
+}
QTEST_MAIN(tst_QQuickItemLayer)
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/data/snapOneItemResize.qml b/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml
new file mode 100644
index 0000000000..7ecc833a64
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+ListView {
+ id: list
+ currentIndex: 5
+ snapMode: ListView.SnapOneItem
+ orientation: ListView.Horizontal
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ highlightFollowsCurrentItem: true
+ model: 10
+ spacing: 10
+ delegate: Item {
+ width: ListView.view.width
+ height: ListView.view.height
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index c93aac456d..472ffdc4b6 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -179,6 +179,7 @@ private slots:
void creationContext();
void snapToItem_data();
void snapToItem();
+ void snapOneItemResize_QTBUG_43555();
void snapOneItem_data();
void snapOneItem();
@@ -241,6 +242,10 @@ private slots:
void QTBUG_39492();
void jsArrayChange();
+ void objectModel();
+
+ void contentHeightWithDelayRemove();
+ void contentHeightWithDelayRemove_data();
private:
template <class T> void items(const QUrl &source);
@@ -391,7 +396,7 @@ void tst_QQuickListView::items(const QUrl &source)
QTRY_VERIFY(contentItem != 0);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->highlightItem() != 0);
QTRY_COMPARE(listview->count(), model.count());
@@ -414,20 +419,20 @@ void tst_QQuickListView::items(const QUrl &source)
// switch to other delegate
testObject->setAnimate(true);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->currentItem());
// set invalid highlight
testObject->setInvalidHighlight(true);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->currentItem());
- QTRY_VERIFY(listview->highlightItem() == 0);
+ QTRY_VERIFY(!listview->highlightItem());
// back to normal highlight
testObject->setInvalidHighlight(false);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->currentItem());
QTRY_VERIFY(listview->highlightItem() != 0);
@@ -439,7 +444,7 @@ void tst_QQuickListView::items(const QUrl &source)
listview->forceLayout();
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QTRY_VERIFY(itemCount == 0);
+ QTRY_COMPARE(itemCount, 0);
QTRY_COMPARE(listview->highlightResizeVelocity(), 1000.0);
QTRY_COMPARE(listview->highlightMoveVelocity(), 100000.0);
@@ -563,7 +568,7 @@ void tst_QQuickListView::inserted(const QUrl &source)
// Insert item outside visible area
model.insertItem(1, "Hello", "1324");
- QTRY_VERIFY(listview->contentY() == 80);
+ QTRY_COMPARE(listview->contentY(), qreal(80));
// Confirm items positioned correctly
for (int i = 5; i < 5+15; ++i) {
@@ -583,7 +588,7 @@ void tst_QQuickListView::inserted(const QUrl &source)
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
QVERIFY(item);
QCOMPARE(item->y(), 0.);
- QTRY_VERIFY(listview->contentY() == 0);
+ QTRY_COMPARE(listview->contentY(), qreal(0));
delete window;
delete testObject;
@@ -916,7 +921,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
// Remove first item (which is the current item);
@@ -968,7 +973,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
}
// Remove current index
- QTRY_VERIFY(listview->currentIndex() == 9);
+ QTRY_COMPARE(listview->currentIndex(), 9);
QQuickItem *oldCurrent = listview->currentItem();
model.removeItem(9);
@@ -1004,7 +1009,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
model.removeItem(6);
QTRY_COMPARE(listview->currentIndex(), 7);
- QTRY_VERIFY(listview->currentItem() == oldCurrent);
+ QTRY_COMPARE(listview->currentItem(), oldCurrent);
listview->setContentY(80);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
@@ -1272,22 +1277,22 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou
model.clear();
QTRY_COMPARE(findItems<QQuickListView>(contentItem, "wrapper").count(), 0);
- QTRY_VERIFY(listview->count() == 0);
- QTRY_VERIFY(listview->currentItem() == 0);
+ QTRY_COMPARE(listview->count(), 0);
+ QTRY_VERIFY(!listview->currentItem());
if (verticalLayoutDirection == QQuickItemView::TopToBottom)
QTRY_COMPARE(listview->contentY(), 0.0);
else
QTRY_COMPARE(listview->contentY(), -listview->height());
- QVERIFY(listview->currentIndex() == -1);
+ QCOMPARE(listview->currentIndex(), -1);
QCOMPARE(listview->contentHeight(), 0.0);
// confirm sanity when adding an item to cleared list
model.addItem("New", "1");
listview->forceLayout();
- QTRY_VERIFY(listview->count() == 1);
+ QTRY_COMPARE(listview->count(), 1);
QVERIFY(listview->currentItem() != 0);
- QVERIFY(listview->currentIndex() == 0);
+ QCOMPARE(listview->currentIndex(), 0);
delete window;
delete testObject;
@@ -1805,7 +1810,7 @@ void tst_QQuickListView::swapWithFirstItem()
// ensure content position is stable
listview->setContentY(0);
model.moveItem(1, 0);
- QTRY_VERIFY(listview->contentY() == 0);
+ QTRY_COMPARE(listview->contentY(), qreal(0));
delete testObject;
delete window;
@@ -1943,11 +1948,11 @@ void tst_QQuickListView::spacing()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
listview->setSpacing(10);
- QTRY_VERIFY(listview->spacing() == 10);
+ QTRY_COMPARE(listview->spacing(), qreal(10));
// Confirm items positioned correctly
QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() == 11);
@@ -1955,7 +1960,7 @@ void tst_QQuickListView::spacing()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*30);
+ QTRY_COMPARE(item->y(), qreal(i*30));
}
listview->setSpacing(0);
@@ -2261,7 +2266,7 @@ void tst_QQuickListView::sectionsDelegate_headerVisibility()
listview->setCurrentIndex(20);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
QTRY_VERIFY(qFuzzyCompare(listview->contentY(), 200.0));
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
listview->setCurrentIndex(0);
QTRY_VERIFY(qFuzzyIsNull(listview->contentY()));
@@ -2682,7 +2687,7 @@ void tst_QQuickListView::currentIndex()
listview->setCurrentIndex(20);
QTRY_VERIFY(listview->verticalVelocity() != 0.0);
listview->setCurrentIndex(0);
- QTRY_VERIFY(listview->verticalVelocity() == 0.0);
+ QTRY_COMPARE(listview->verticalVelocity(), 0.0);
// footer should become visible if it is out of view, and then current index is set to count-1
window->rootObject()->setProperty("showFooter", true);
@@ -2704,7 +2709,7 @@ void tst_QQuickListView::currentIndex()
// turn off auto highlight
listview->setHighlightFollowsCurrentItem(false);
- QVERIFY(listview->highlightFollowsCurrentItem() == false);
+ QVERIFY(!listview->highlightFollowsCurrentItem());
QVERIFY(listview->highlightItem());
qreal hlPos = listview->highlightItem()->y();
@@ -2808,7 +2813,7 @@ void tst_QQuickListView::keyNavigation()
window->requestActivate();
QTest::qWaitForWindowActive(window);
- QTRY_VERIFY(qGuiApp->focusWindow() == window);
+ QTRY_COMPARE(qGuiApp->focusWindow(), window);
QTest::keyClick(window, forwardsKey);
QCOMPARE(listview->currentIndex(), 1);
@@ -2917,7 +2922,7 @@ void tst_QQuickListView::itemList()
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
QTRY_VERIFY(model != 0);
- QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
@@ -2958,7 +2963,7 @@ void tst_QQuickListView::itemListFlicker()
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
QTRY_VERIFY(model != 0);
- QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
QQuickItem *item;
@@ -3024,14 +3029,14 @@ void tst_QQuickListView::cacheBuffer()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
QQmlIncubationController controller;
window->engine()->setIncubationController(&controller);
testObject->setCacheBuffer(200);
- QTRY_VERIFY(listview->cacheBuffer() == 200);
+ QTRY_COMPARE(listview->cacheBuffer(), 200);
// items will be created one at a time
for (int i = itemCount; i < qMin(itemCount+10,model.count()); ++i) {
@@ -3057,7 +3062,7 @@ void tst_QQuickListView::cacheBuffer()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
// move view and confirm items in view are visible immediately and outside are created async
@@ -3067,7 +3072,7 @@ void tst_QQuickListView::cacheBuffer()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QVERIFY(item);
- QVERIFY(item->y() == i*20);
+ QCOMPARE(item->y(), qreal(i*20));
}
QVERIFY(findItem<QQuickItem>(listview, "wrapper", 32) == 0);
@@ -3528,7 +3533,7 @@ void tst_QQuickListView::QTBUG_11105()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
listview->positionViewAtIndex(20, QQuickListView::Beginning);
@@ -3622,7 +3627,7 @@ void tst_QQuickListView::header()
QQuickText *header = 0;
QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header"));
- QVERIFY(header == listview->headerItem());
+ QCOMPARE(header, listview->headerItem());
QCOMPARE(header->width(), 100.);
QCOMPARE(header->height(), 30.);
@@ -3660,7 +3665,7 @@ void tst_QQuickListView::header()
header = findItem<QQuickText>(contentItem, "header2");
QVERIFY(header);
- QVERIFY(header == listview->headerItem());
+ QCOMPARE(header, listview->headerItem());
QCOMPARE(header->position(), changedHeaderPos);
QCOMPARE(header->width(), 50.);
@@ -3811,7 +3816,7 @@ void tst_QQuickListView::headerChangesViewport()
QQuickText *header = 0;
QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header"));
- QVERIFY(header == listview->headerItem());
+ QCOMPARE(header, listview->headerItem());
QCOMPARE(header->height(), 20.);
QCOMPARE(listview->contentHeight(), 20.);
@@ -3862,7 +3867,7 @@ void tst_QQuickListView::footer()
QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
QVERIFY(footer);
- QVERIFY(footer == listview->footerItem());
+ QCOMPARE(footer, listview->footerItem());
QCOMPARE(footer->position(), initialFooterPos);
QCOMPARE(footer->width(), 100.);
@@ -3922,7 +3927,7 @@ void tst_QQuickListView::footer()
footer = findItem<QQuickText>(contentItem, "footer2");
QVERIFY(footer);
- QVERIFY(footer == listview->footerItem());
+ QCOMPARE(footer, listview->footerItem());
QCOMPARE(footer->position(), changedFooterPos);
QCOMPARE(footer->width(), 50.);
@@ -4155,11 +4160,11 @@ void tst_QQuickListView::resetModel_headerFooter()
// A reset should not force a new header or footer to be created.
QQuickItem *newHeader = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(newHeader == header);
+ QCOMPARE(newHeader, header);
QCOMPARE(header->y(), -header->height());
QQuickItem *newFooter = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(newFooter == footer);
+ QCOMPARE(newFooter, footer);
QCOMPARE(footer->y(), 30.*4);
delete window;
@@ -4664,7 +4669,7 @@ void tst_QQuickListView::indexAt_itemAt()
QVERIFY(item);
}
QCOMPARE(listview->indexAt(x,y), index);
- QVERIFY(listview->itemAt(x,y) == item);
+ QCOMPARE(listview->itemAt(x,y), item);
releaseView(window);
delete testObject;
@@ -4828,7 +4833,7 @@ void tst_QQuickListView::rightToLeft()
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
QTRY_VERIFY(model != 0);
- QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
// initial position at first item, right edge aligned
@@ -4893,7 +4898,7 @@ void tst_QQuickListView::test_mirroring()
foreach (const QString objectName, objectNames)
QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
- QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
+ QCOMPARE(listviewB->layoutDirection(), listviewB->effectiveLayoutDirection());
QQuickItemPrivate::get(listviewB)->setLayoutMirror(true);
QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
@@ -5034,7 +5039,7 @@ void tst_QQuickListView::marginsResize()
// flick past the end and check content pos still settles on correct extents
flick(window, flickStart, flickEnd, 180);
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
if (orientation == QQuickListView::Vertical)
QTRY_COMPARE(listview->contentY(), end);
else
@@ -5049,7 +5054,7 @@ void tst_QQuickListView::marginsResize()
// flick past the beginning and check content pos still settles on correct extents
flick(window, flickEnd, flickStart, 180);
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
if (orientation == QQuickListView::Vertical)
QTRY_COMPARE(listview->contentY(), start);
else
@@ -5199,6 +5204,37 @@ void tst_QQuickListView::snapToItem()
releaseView(window);
}
+void tst_QQuickListView::snapOneItemResize_QTBUG_43555()
+{
+ QQuickView *window = createView();
+ window->resize(QSize(100, 320));
+ window->setResizeMode(QQuickView::SizeRootObjectToView);
+ QQuickViewTestUtil::moveMouseAway(window);
+
+ window->setSource(testFileUrl("snapOneItemResize.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
+
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_COMPARE(listview->currentIndex(), 5);
+ currentIndexSpy.clear();
+
+ window->resize(QSize(400, 320));
+
+ QTRY_COMPARE(int(listview->width()), 400);
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
+ QTRY_COMPARE(listview->currentIndex(), 5);
+ QCOMPARE(currentIndexSpy.count(), 0);
+
+ delete window;
+}
+
void tst_QQuickListView::qAbstractItemModel_package_items()
{
items<QaimModel>(testFileUrl("listviewtest-package.qml"));
@@ -7006,7 +7042,7 @@ void tst_QQuickListView::matchIndexLists(const QVariantList &indexLists, const Q
void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes)
{
for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) {
- QVERIFY(it.value().type() == QVariant::Int);
+ QCOMPARE(it.value().type(), QVariant::Int);
QString name = it.key();
int itemIndex = it.value().toInt();
QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
@@ -7020,7 +7056,7 @@ void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const Qa
void tst_QQuickListView::matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems)
{
for (int i=0; i<itemLists.count(); i++) {
- QVERIFY(itemLists[i].type() == QVariant::List);
+ QCOMPARE(itemLists[i].type(), QVariant::List);
QVariantList current = itemLists[i].toList();
for (int j=0; j<current.count(); j++) {
QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>());
@@ -7062,7 +7098,7 @@ void tst_QQuickListView::flickBeyondBounds()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*45);
+ QTRY_COMPARE(item->y(), qreal(i*45));
}
delete window;
@@ -7856,7 +7892,7 @@ void tst_QQuickListView::QTBUG_38209()
// simulate mouse flick
flick(window.data(), QPoint(200, 200), QPoint(200, 50), 100);
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
qreal contentY = listview->contentY();
// flick down
@@ -8063,6 +8099,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/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 3dd2551d9d..e72b38e06c 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -236,7 +236,7 @@ void tst_QQuickLoader::clear()
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
- QTRY_VERIFY(loader->item() == 0);
+ QTRY_VERIFY(!loader->item());
QCOMPARE(loader->progress(), 0.0);
QCOMPARE(loader->status(), QQuickLoader::Null);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
@@ -256,7 +256,7 @@ void tst_QQuickLoader::clear()
loader->setSourceComponent(0);
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
QCOMPARE(loader->progress(), 0.0);
QCOMPARE(loader->status(), QQuickLoader::Null);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
@@ -276,7 +276,7 @@ void tst_QQuickLoader::clear()
QMetaObject::invokeMethod(item, "clear");
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
QCOMPARE(loader->progress(), 0.0);
QCOMPARE(loader->status(), QQuickLoader::Null);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
@@ -447,7 +447,7 @@ void tst_QQuickLoader::networkRequestUrl()
QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
QVERIFY(loader != 0);
- QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
+ QTRY_COMPARE(loader->status(), QQuickLoader::Ready);
QVERIFY(loader->item());
QCOMPARE(loader->progress(), 1.0);
@@ -480,7 +480,7 @@ void tst_QQuickLoader::networkComponent()
QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->children().at(1));
QVERIFY(loader);
- QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
+ QTRY_COMPARE(loader->status(), QQuickLoader::Ready);
QVERIFY(loader->item());
QCOMPARE(loader->progress(), 1.0);
@@ -505,9 +505,9 @@ void tst_QQuickLoader::failNetworkRequest()
QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
QVERIFY(loader != 0);
- QTRY_VERIFY(loader->status() == QQuickLoader::Error);
+ QTRY_COMPARE(loader->status(), QQuickLoader::Error);
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->property("did_load").toInt(), 123);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
@@ -525,11 +525,11 @@ void tst_QQuickLoader::active()
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader->active() == false); // set manually to false
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
QMetaObject::invokeMethod(object, "doSetSourceComponent");
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
QMetaObject::invokeMethod(object, "doSetSource");
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
QMetaObject::invokeMethod(object, "doSetActive");
QVERIFY(loader->item() != 0);
@@ -598,7 +598,7 @@ void tst_QQuickLoader::active()
QVERIFY(loader->item() != 0);
int currItemChangedCount = loader->property("itemChangedCount").toInt();
QMetaObject::invokeMethod(object, "doSetInactive");
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
QCOMPARE(loader->property("itemChangedCount").toInt(), (currItemChangedCount+1));
delete object;
@@ -781,7 +781,7 @@ void tst_QQuickLoader::initialPropertyValuesError()
QVERIFY(object != 0);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader != 0);
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
delete object;
}
@@ -803,7 +803,7 @@ void tst_QQuickLoader::deleteComponentCrash()
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
QTRY_COMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
- QVERIFY(loader->source() == testFileUrl("BlueRect.qml"));
+ QCOMPARE(loader->source(), testFileUrl("BlueRect.qml"));
delete item;
}
@@ -833,7 +833,7 @@ void tst_QQuickLoader::vmeErrors()
QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
QVERIFY(loader);
- QVERIFY(loader->item() == 0);
+ QVERIFY(!loader->item());
delete loader;
}
@@ -1098,7 +1098,7 @@ void tst_QQuickLoader::parented()
QQuickItem *item = root->findChild<QQuickItem*>("comp");
QVERIFY(item);
- QVERIFY(item->parentItem() == root);
+ QCOMPARE(item->parentItem(), root);
QCOMPARE(item->width(), 300.);
QCOMPARE(item->height(), 300.);
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index da8bb9e94d..6e6c9da829 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -169,7 +169,7 @@ void tst_QQuickMouseArea::dragProperties()
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QQuickItem *rootItem = qobject_cast<QQuickItem*>(window.rootObject());
QVERIFY(rootItem != 0);
QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
@@ -267,14 +267,14 @@ void tst_QQuickMouseArea::resetDrag()
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QQuickItem *rootItem = qobject_cast<QQuickItem*>(window.rootObject());
QVERIFY(rootItem != 0);
QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
QVERIFY(drag->target() != 0);
window.rootContext()->setContextProperty("haveTarget", QVariant(false));
QCOMPARE(targetSpy.count(),1);
- QVERIFY(drag->target() == 0);
+ QVERIFY(!drag->target());
}
void tst_QQuickMouseArea::dragging()
@@ -300,7 +300,7 @@ void tst_QQuickMouseArea::dragging()
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
@@ -347,7 +347,7 @@ void tst_QQuickMouseArea::dragSmoothed()
mouseRegion->setAcceptedButtons(Qt::LeftButton);
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
QVERIFY(!drag->active());
@@ -393,7 +393,7 @@ void tst_QQuickMouseArea::dragThreshold()
mouseRegion->setAcceptedButtons(Qt::LeftButton);
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
QVERIFY(!drag->active());
@@ -451,7 +451,7 @@ void tst_QQuickMouseArea::invalidDrag()
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
@@ -501,7 +501,7 @@ void tst_QQuickMouseArea::cancelDragging()
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
@@ -655,7 +655,7 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
QGuiApplication::sendEvent(&window, &pressEvent);
- QVERIFY(mouseArea->pressedButtons() == Qt::LeftButton);
+ QCOMPARE(mouseArea->pressedButtons(), Qt::LeftButton);
QVERIFY(!window.rootObject()->property("clicked").toBool());
QVERIFY(!window.rootObject()->property("held").toBool());
@@ -1268,7 +1268,7 @@ void tst_QQuickMouseArea::disableAfterPress()
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
@@ -1561,7 +1561,7 @@ void tst_QQuickMouseArea::changeAxis()
// target
QQuickItem *blackRect = view.rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
+ QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
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/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index e69ebfa8fe..4da4767d7b 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -719,7 +719,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QTest::mouseMove(window.data(), p1);
QQuickTouchUtils::flush(window.data());
- QVERIFY(flickable->contentY() == 0);
+ QCOMPARE(flickable->contentY(), qreal(0));
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -1186,14 +1186,14 @@ void tst_QQuickMultiPointTouchArea::mouseInteraction()
QPoint p1 = QPoint(100, 100);
QTest::mousePress(view.data(), (Qt::MouseButton) buttons, 0, p1);
QCOMPARE(area->property("touchCount").toInt(), accept);
- QCOMPARE(point1->pressed(), accept);
+ QCOMPARE(point1->pressed(), accept != 0);
p1 += QPoint(10, 10);
QTest::mouseMove(view.data(), p1);
- QCOMPARE(point1->pressed(), accept);
+ QCOMPARE(point1->pressed(), accept != 0);
QCOMPARE(area->property("touchCount").toInt(), accept);
p1 += QPoint(10, 10);
QTest::mouseMove(view.data(), p1);
- QCOMPARE(point1->pressed(), accept);
+ QCOMPARE(point1->pressed(), accept != 0);
QCOMPARE(area->property("touchCount").toInt(), accept);
QTest::mouseRelease(view.data(), (Qt::MouseButton) buttons);
QCOMPARE(point1->pressed(), false);
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..eed947bfcd 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
@@ -183,8 +185,8 @@ void tst_QQuickPathView::initValues()
QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
QVERIFY(obj != 0);
- QVERIFY(obj->path() == 0);
- QVERIFY(obj->delegate() == 0);
+ QVERIFY(!obj->path());
+ QVERIFY(!obj->delegate());
QCOMPARE(obj->model(), QVariant());
QCOMPARE(obj->currentIndex(), 0);
QCOMPARE(obj->offset(), 0.);
@@ -799,7 +801,7 @@ void tst_QQuickPathView::dataModel()
QVERIFY(pathview != 0);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
+ QVERIFY(!testObject->error());
QQuickItem *item = findItem<QQuickItem>(pathview, "wrapper", 0);
QVERIFY(item);
@@ -828,14 +830,14 @@ void tst_QQuickPathView::dataModel()
testObject->setPathItemCount(5);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
+ QVERIFY(!testObject->error());
QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
QQuickRectangle *testItem = findItem<QQuickRectangle>(pathview, "wrapper", 4);
QVERIFY(testItem != 0);
testItem = findItem<QQuickRectangle>(pathview, "wrapper", 5);
- QVERIFY(testItem == 0);
+ QVERIFY(!testItem);
pathview->setCurrentIndex(1);
QCOMPARE(pathview->currentIndex(), 1);
@@ -1814,7 +1816,7 @@ void tst_QQuickPathView::cancelDrag()
item->grabMouse();
// returns to a snap point.
- QTRY_VERIFY(pathview->offset() == qFloor(pathview->offset()));
+ QTRY_COMPARE(pathview->offset(), qreal(qFloor(pathview->offset())));
QTRY_VERIFY(!pathview->isMoving());
QVERIFY(!pathview->isDragging());
QCOMPARE(draggingSpy.count(), 2);
@@ -1897,7 +1899,7 @@ void tst_QQuickPathView::snapToItem()
QVERIFY(pathview->isMoving());
QTRY_VERIFY_WITH_TIMEOUT(!pathview->isMoving(), 50000);
- QVERIFY(pathview->offset() == qFloor(pathview->offset()));
+ QCOMPARE(pathview->offset(), qreal(qFloor(pathview->offset())));
if (enforceRange)
QVERIFY(pathview->currentIndex() != currentIndex);
@@ -2051,7 +2053,7 @@ void tst_QQuickPathView::indexAt_itemAt()
QVERIFY(item);
}
QCOMPARE(pathview->indexAt(x,y), index);
- QVERIFY(pathview->itemAt(x,y) == item);
+ QCOMPARE(pathview->itemAt(x,y), item);
}
@@ -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/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
index 8063453993..3988a90aed 100644
--- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
+++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
@@ -91,7 +91,7 @@ void tst_QQuickPinchArea::pinchProperties()
// target
QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
QVERIFY(blackRect != 0);
- QVERIFY(blackRect == pinch->target());
+ QCOMPARE(blackRect, pinch->target());
QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
QVERIFY(rootItem != 0);
QSignalSpy targetSpy(pinch, SIGNAL(targetChanged()));
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index b9f93a4dcf..0064212a78 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"));
}
@@ -159,10 +161,10 @@ void tst_qquickpixmapcache::single()
if (incache) {
QCOMPARE(pixmap.error(), expectedError);
if (exists) {
- QVERIFY(pixmap.status() == QQuickPixmap::Ready);
+ QCOMPARE(pixmap.status(), QQuickPixmap::Ready);
QVERIFY(pixmap.width() > 0);
} else {
- QVERIFY(pixmap.status() == QQuickPixmap::Error);
+ QCOMPARE(pixmap.status(), QQuickPixmap::Error);
QVERIFY(pixmap.width() <= 0);
}
} else {
@@ -174,10 +176,10 @@ void tst_qquickpixmapcache::single()
QVERIFY(!QTestEventLoop::instance().timeout());
QVERIFY(getter.gotslot);
if (exists) {
- QVERIFY(pixmap.status() == QQuickPixmap::Ready);
+ QCOMPARE(pixmap.status(), QQuickPixmap::Ready);
QVERIFY(pixmap.width() > 0);
} else {
- QVERIFY(pixmap.status() == QQuickPixmap::Error);
+ QCOMPARE(pixmap.status(), QQuickPixmap::Error);
QVERIFY(pixmap.width() <= 0);
}
QCOMPARE(pixmap.error(), expectedError);
@@ -259,7 +261,9 @@ void tst_qquickpixmapcache::parallel()
}
}
- QCOMPARE(incache+slotters, targets.count());
+ if (incache + slotters != targets.count())
+ QFAIL(QString::fromLatin1("pixmap counts don't add up: %1 incache, %2 slotters, %3 total")
+ .arg(incache).arg(slotters).arg(targets.count()).toLatin1().constData());
if (cancel >= 0) {
pixmaps.at(cancel)->clear(getters[cancel]);
@@ -280,7 +284,12 @@ void tst_qquickpixmapcache::parallel()
if (pending[i])
QVERIFY(getters[i]->gotslot);
- QVERIFY(pixmap->isReady());
+ if (!pixmap->isReady()) {
+ QFAIL(QString::fromLatin1("pixmap %1 not ready, status %2: %3")
+ .arg(pixmap->url().toString()).arg(pixmap->status())
+ .arg(pixmap->error()).toLatin1().constData());
+
+ }
QVERIFY(pixmap->width() > 0);
delete getters[i];
}
@@ -307,7 +316,7 @@ void tst_qquickpixmapcache::massive()
QVERIFY(p2.isReady());
QVERIFY(p2.image().size() == QSize(10000, 1000));
- QVERIFY(p2.image().cacheKey() == cachekey);
+ QCOMPARE(p2.image().cacheKey(), cachekey);
}
// Confirm that massive images are removed from the cache when
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..69359503fe 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);
@@ -1998,12 +3847,63 @@ void tst_qquickpositioners::test_allInvisible()
QQuickRow *row = window->rootObject()->findChild<QQuickRow*>("row");
QVERIFY(row != 0);
- QVERIFY(row->width() == 0);
- QVERIFY(row->height() == 0);
+ QCOMPARE(row->width(), qreal(0));
+ QCOMPARE(row->height(), qreal(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);
+ QCOMPARE(column->width(), qreal(0));
+ QCOMPARE(column->height(), qreal(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);
+ QCOMPARE(grid->width(), qreal(0));
+ QCOMPARE(grid->height(), qreal(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);
+ QCOMPARE(flow->width(), qreal(0));
+ QCOMPARE(flow->height(), qreal(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()
@@ -2017,30 +3917,30 @@ void tst_qquickpositioners::test_attachedproperties()
QVERIFY(greenRect != 0);
int posIndex = greenRect->property("posIndex").toInt();
- QVERIFY(posIndex == 0);
+ QCOMPARE(posIndex, 0);
bool isFirst = greenRect->property("isFirstItem").toBool();
- QVERIFY(isFirst == true);
+ QVERIFY(isFirst);
bool isLast = greenRect->property("isLastItem").toBool();
- QVERIFY(isLast == false);
+ QVERIFY(!isLast);
QQuickRectangle *yellowRect = window->rootObject()->findChild<QQuickRectangle *>("yellowRect");
QVERIFY(yellowRect != 0);
posIndex = yellowRect->property("posIndex").toInt();
- QVERIFY(posIndex == -1);
+ QCOMPARE(posIndex, -1);
isFirst = yellowRect->property("isFirstItem").toBool();
- QVERIFY(isFirst == false);
+ QVERIFY(!isFirst);
isLast = yellowRect->property("isLastItem").toBool();
- QVERIFY(isLast == false);
+ QVERIFY(!isLast);
yellowRect->metaObject()->invokeMethod(yellowRect, "onDemandPositioner");
posIndex = yellowRect->property("posIndex").toInt();
- QVERIFY(posIndex == 1);
+ QCOMPARE(posIndex, 1);
isFirst = yellowRect->property("isFirstItem").toBool();
- QVERIFY(isFirst == false);
+ QVERIFY(!isFirst);
isLast = yellowRect->property("isLastItem").toBool();
- QVERIFY(isLast == true);
+ QVERIFY(isLast);
}
@@ -2066,46 +3966,46 @@ void tst_qquickpositioners::test_attachedproperties_dynamic()
QVERIFY(rect0 != 0);
int posIndex = rect0->property("index").toInt();
- QVERIFY(posIndex == 0);
+ QCOMPARE(posIndex, 0);
bool isFirst = rect0->property("firstItem").toBool();
- QVERIFY(isFirst == true);
+ QVERIFY(isFirst);
bool isLast = rect0->property("lastItem").toBool();
- QVERIFY(isLast == false);
+ QVERIFY(!isLast);
QQuickRectangle *rect1 = window->rootObject()->findChild<QQuickRectangle *>("rect1");
QVERIFY(rect1 != 0);
posIndex = rect1->property("index").toInt();
- QVERIFY(posIndex == 1);
+ QCOMPARE(posIndex, 1);
isFirst = rect1->property("firstItem").toBool();
- QVERIFY(isFirst == false);
+ QVERIFY(!isFirst);
isLast = rect1->property("lastItem").toBool();
- QVERIFY(isLast == true);
+ QVERIFY(isLast);
row->metaObject()->invokeMethod(row, "createSubRect");
- QTRY_VERIFY(rect1->property("index").toInt() == 1);
- QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
- QTRY_VERIFY(rect1->property("lastItem").toBool() == false);
+ QTRY_COMPARE(rect1->property("index").toInt(), 1);
+ QTRY_VERIFY(!rect1->property("firstItem").toBool());
+ QTRY_VERIFY(!rect1->property("lastItem").toBool());
QQuickRectangle *rect2 = window->rootObject()->findChild<QQuickRectangle *>("rect2");
QVERIFY(rect2 != 0);
posIndex = rect2->property("index").toInt();
- QVERIFY(posIndex == 2);
+ QCOMPARE(posIndex, 2);
isFirst = rect2->property("firstItem").toBool();
- QVERIFY(isFirst == false);
+ QVERIFY(!isFirst);
isLast = rect2->property("lastItem").toBool();
- QVERIFY(isLast == true);
+ QVERIFY(isLast);
row->metaObject()->invokeMethod(row, "destroySubRect");
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
- QTRY_VERIFY(rect1->property("index").toInt() == 1);
- QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
- QTRY_VERIFY(rect1->property("lastItem").toBool() == true);
+ QTRY_COMPARE(rect1->property("index").toInt(), 1);
+ QTRY_VERIFY(!rect1->property("firstItem").toBool());
+ QTRY_VERIFY(rect1->property("lastItem").toBool());
}
@@ -2138,7 +4038,7 @@ void tst_qquickpositioners::matchIndexLists(const QVariantList &indexLists, cons
void tst_qquickpositioners::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes)
{
for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) {
- QVERIFY(it.value().type() == QVariant::Int);
+ QCOMPARE(it.value().type(), QVariant::Int);
QString name = it.key();
int itemIndex = it.value().toInt();
QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
@@ -2152,7 +4052,7 @@ void tst_qquickpositioners::matchItemsAndIndexes(const QVariantMap &items, const
void tst_qquickpositioners::matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems)
{
for (int i=0; i<itemLists.count(); i++) {
- QVERIFY(itemLists[i].type() == QVariant::List);
+ QCOMPARE(itemLists[i].type(), QVariant::List);
QVariantList current = itemLists[i].toList();
for (int j=0; j<current.count(); j++) {
QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>());
diff --git a/tests/auto/quick/qquickrepeater/data/modelCleared.qml b/tests/auto/quick/qquickrepeater/data/modelCleared.qml
new file mode 100644
index 0000000000..1269e9bdf2
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/modelCleared.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+
+Row {
+ spacing: 2
+ height: 100
+
+ Repeater {
+ id: repeater
+ objectName: "repeater"
+ model: 10
+ Rectangle {
+ color: "green"
+ width: 10; height: 50
+ anchors.bottom: parent.bottom
+ }
+ }
+}
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..a34001b23a 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"
@@ -67,6 +68,7 @@ private slots:
void resetModel();
void modelChanged();
void modelReset();
+ void modelCleared();
void properties();
void asynchronous();
void initParent();
@@ -76,6 +78,8 @@ private slots:
void jsArrayChange();
void clearRemovalOrder();
void destroyCount();
+ void stackingOrder();
+ void objectModel();
};
class TestObject : public QObject
@@ -128,7 +132,7 @@ void tst_QQuickRepeater::numberModel()
QVERIFY(!repeater->itemAt(repeater->count()));
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
+ QVERIFY(!testObject->error());
delete testObject;
delete window;
@@ -440,19 +444,19 @@ void tst_QQuickRepeater::itemModel()
testObject->setUseModel(true);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
+ QVERIFY(!testObject->error());
QCOMPARE(container->childItems().count(), 4);
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item1");
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item2");
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(2))->objectName() == "item3");
- QVERIFY(container->childItems().at(3) == repeater);
+ QCOMPARE(qobject_cast<QObject*>(container->childItems().at(0))->objectName(), QLatin1String("item1"));
+ QCOMPARE(qobject_cast<QObject*>(container->childItems().at(1))->objectName(), QLatin1String("item2"));
+ QCOMPARE(qobject_cast<QObject*>(container->childItems().at(2))->objectName(), QLatin1String("item3"));
+ QCOMPARE(container->childItems().at(3), repeater);
QMetaObject::invokeMethod(window->rootObject(), "switchModel");
QCOMPARE(container->childItems().count(), 3);
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item4");
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item5");
- QVERIFY(container->childItems().at(2) == repeater);
+ QCOMPARE(qobject_cast<QObject*>(container->childItems().at(0))->objectName(), QLatin1String("item4"));
+ QCOMPARE(qobject_cast<QObject*>(container->childItems().at(1))->objectName(), QLatin1String("item5"));
+ QCOMPARE(container->childItems().at(2), repeater);
testObject->setUseModel(false);
QCOMPARE(container->childItems().count(), 1);
@@ -631,6 +635,26 @@ void tst_QQuickRepeater::modelReset()
QCOMPARE(addedSpy.count(), 0);
}
+// QTBUG-46828
+void tst_QQuickRepeater::modelCleared()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("modelCleared.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(rootObject);
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
+ QVERIFY(repeater);
+
+ // verify no error messages when the model is cleared and the items are destroyed
+ QQmlTestMessageHandler messageHandler;
+ repeater->setModel(0);
+ QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
+
+ delete rootObject;
+}
+
void tst_QQuickRepeater::properties()
{
QQmlEngine engine;
@@ -788,8 +812,8 @@ void tst_QQuickRepeater::invalidContextCrash()
repeater->setParent(root.data());
QCOMPARE(root->children().count(), 2);
- QVERIFY(root->children().at(0) == model);
- QVERIFY(root->children().at(1) == repeater);
+ QCOMPARE(root->children().at(0), model);
+ QCOMPARE(root->children().at(1), repeater);
// Delete the root object, which will invalidate/delete the QML context
// and then delete the child QObjects, which may try to access the context.
@@ -894,6 +918,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/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
index 04fdc4ecf7..10e91c455b 100644
--- a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
+++ b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
@@ -130,9 +130,9 @@ void tst_qquicksmoothedanimation::simpleAnimation()
animation->setProperty("x");
animation->setTo(200);
animation->setDuration(250);
- QVERIFY(animation->target() == rect);
- QVERIFY(animation->property() == "x");
- QVERIFY(animation->to() == 200);
+ QCOMPARE(animation->target(), rect);
+ QCOMPARE(animation->property(), QLatin1String("x"));
+ QCOMPARE(animation->to(), qreal(200));
animation->start();
QVERIFY(animation->isRunning());
QTest::qWait(animation->duration());
@@ -147,7 +147,7 @@ void tst_qquicksmoothedanimation::simpleAnimation()
QVERIFY(animation->isRunning());
QVERIFY(animation->isPaused());
animation->setCurrentTime(125);
- QVERIFY(animation->currentTime() == 125);
+ QCOMPARE(animation->currentTime(), 125);
QCOMPARE(rect->x(), qreal(100));
}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 6c42a7a0ee..a375a55877 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -1241,7 +1241,7 @@ void tst_qquickstates::deletingState()
QVERIFY(state != 0);
delete state;
- QVERIFY(sg->findState("blue") == 0);
+ QVERIFY(!sg->findState("blue"));
//### should we warn that state doesn't exist
sg->setState("blue");
@@ -1317,7 +1317,7 @@ void tst_qquickstates::illegalObjectCreation()
QQmlComponent component(&engine, testFileUrl("illegalObj.qml"));
QList<QQmlError> errors = component.errors();
- QVERIFY(errors.count() == 1);
+ QCOMPARE(errors.count(), 1);
const QQmlError &error = errors.at(0);
QCOMPARE(error.line(), 9);
QCOMPARE(error.column(), 23);
@@ -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 816440b191..4678f5fbb9 100644
--- a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
+++ b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
@@ -171,16 +171,16 @@ 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) {
QCOMPARE(layoutFormats.at(i).start, formats.at(i).start);
QCOMPARE(layoutFormats.at(i).length, formats.at(i).length);
if (formats.at(i).type & Format::Bold)
- QVERIFY(layoutFormats.at(i).format.fontWeight() == QFont::Bold);
+ QCOMPARE(layoutFormats.at(i).format.fontWeight(), int(QFont::Bold));
else
- QVERIFY(layoutFormats.at(i).format.fontWeight() == QFont::Normal);
+ QCOMPARE(layoutFormats.at(i).format.fontWeight(), int(QFont::Normal));
QVERIFY(layoutFormats.at(i).format.fontItalic() == bool(formats.at(i).type & Format::Italic));
QVERIFY(layoutFormats.at(i).format.fontUnderline() == bool(formats.at(i).type & Format::Underline));
}
@@ -200,7 +200,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/qquicksystempalette/tst_qquicksystempalette.cpp b/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
index 5c0c5fd8d3..a4c4987ad9 100644
--- a/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
+++ b/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
@@ -97,7 +97,7 @@ void tst_qquicksystempalette::inactivePalette()
QQuickSystemPalette *object = qobject_cast<QQuickSystemPalette*>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->colorGroup() == QQuickSystemPalette::Inactive);
+ QCOMPARE(object->colorGroup(), QQuickSystemPalette::Inactive);
QPalette palette;
palette.setCurrentColorGroup(QPalette::Inactive);
@@ -127,7 +127,7 @@ void tst_qquicksystempalette::disabledPalette()
QQuickSystemPalette *object = qobject_cast<QQuickSystemPalette*>(component.create());
QVERIFY(object != 0);
- QVERIFY(object->colorGroup() == QQuickSystemPalette::Disabled);
+ QCOMPARE(object->colorGroup(), QQuickSystemPalette::Disabled);
QPalette palette;
palette.setCurrentColorGroup(QPalette::Disabled);
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..c1f10f9788 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;
@@ -240,7 +242,7 @@ void tst_qquicktext::text()
QVERIFY(textObject != 0);
QCOMPARE(textObject->text(), QString(""));
- QVERIFY(textObject->width() == 0);
+ QCOMPARE(textObject->width(), qreal(0));
delete textObject;
}
@@ -357,7 +359,7 @@ void tst_qquicktext::width()
QVERIFY(doc != 0);
QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
- QVERIFY(textObject->textFormat() == QQuickText::RichText);
+ QCOMPARE(textObject->textFormat(), QQuickText::RichText);
delete textObject;
}
@@ -374,7 +376,7 @@ void tst_qquicktext::wrap()
textHeight = textObject->height();
QVERIFY(textObject != 0);
- QVERIFY(textObject->wrapMode() == QQuickText::WordWrap);
+ QCOMPARE(textObject->wrapMode(), QQuickText::WordWrap);
QCOMPARE(textObject->width(), 300.);
delete textObject;
@@ -657,11 +659,11 @@ void tst_qquicktext::textFormat()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickText::RichText);
+ QCOMPARE(textObject->textFormat(), QQuickText::RichText);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
QVERIFY(textPrivate != 0);
- QVERIFY(textPrivate->richText == true);
+ QVERIFY(textPrivate->richText);
delete textObject;
}
@@ -671,11 +673,11 @@ void tst_qquicktext::textFormat()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickText::AutoText);
+ QCOMPARE(textObject->textFormat(), QQuickText::AutoText);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
QVERIFY(textPrivate != 0);
- QVERIFY(textPrivate->styledText == true);
+ QVERIFY(textPrivate->styledText);
delete textObject;
}
@@ -685,7 +687,7 @@ void tst_qquicktext::textFormat()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickText::PlainText);
+ QCOMPARE(textObject->textFormat(), QQuickText::PlainText);
delete textObject;
}
@@ -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"));
@@ -2126,8 +2136,8 @@ void tst_qquicktext::lineHeight()
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
QVERIFY(myText != 0);
- QVERIFY(myText->lineHeight() == 1);
- QVERIFY(myText->lineHeightMode() == QQuickText::ProportionalHeight);
+ QCOMPARE(myText->lineHeight(), qreal(1));
+ QCOMPARE(myText->lineHeightMode(), QQuickText::ProportionalHeight);
qreal h = myText->height();
myText->setLineHeight(1.5);
@@ -2197,12 +2207,12 @@ void tst_qquicktext::implicitSize()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject->width() < textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
QCOMPARE(textObject->property("iWidth").toReal(), textObject->implicitWidth());
textObject->resetWidth();
- QVERIFY(textObject->width() == textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
delete textObject;
}
@@ -2738,7 +2748,7 @@ void tst_qquicktext::lineLaidOut()
QVERIFY(r.x() == r.width() + 30);
if (i >= 60) {
QVERIFY(r.x() == r.width() * 2 + 60);
- QVERIFY(r.height() == 20);
+ QCOMPARE(r.height(), qreal(20));
}
}
@@ -2916,7 +2926,7 @@ void tst_qquicktext::imgTagsAlign()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
- QVERIFY(textObject->height() == imgHeight);
+ QCOMPARE(textObject->height(), qreal(imgHeight));
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
QVERIFY(textPrivate != 0);
@@ -2927,7 +2937,7 @@ void tst_qquicktext::imgTagsAlign()
else if (align == "middle")
QVERIFY(br.y() == imgHeight / 2.0 - br.height() / 2.0);
else if (align == "top")
- QVERIFY(br.y() == 0);
+ QCOMPARE(br.y(), qreal(0));
delete textObject;
}
@@ -2941,11 +2951,11 @@ void tst_qquicktext::imgTagsMultipleImages()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
- QVERIFY(textObject->height() == 85);
+ QCOMPARE(textObject->height(), qreal(85));
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
QVERIFY(textPrivate != 0);
- QVERIFY(textPrivate->extra->visibleImgTags.count() == 2);
+ QCOMPARE(textPrivate->extra->visibleImgTags.count(), 2);
delete textObject;
}
@@ -2958,9 +2968,9 @@ void tst_qquicktext::imgTagsElide()
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
QVERIFY(textPrivate != 0);
- QVERIFY(textPrivate->extra->visibleImgTags.count() == 0);
+ QCOMPARE(textPrivate->extra->visibleImgTags.count(), 0);
myText->setMaximumLineCount(20);
- QTRY_VERIFY(textPrivate->extra->visibleImgTags.count() == 1);
+ QTRY_COMPARE(textPrivate->extra->visibleImgTags.count(), 1);
delete myText;
delete window;
@@ -2978,16 +2988,16 @@ void tst_qquicktext::imgTagsUpdates()
QVERIFY(textPrivate != 0);
myText->setText("This is a heart<img src=\"images/heart200.png\">.");
- QVERIFY(textPrivate->extra->visibleImgTags.count() == 1);
- QVERIFY(spy.count() == 1);
+ QCOMPARE(textPrivate->extra->visibleImgTags.count(), 1);
+ QCOMPARE(spy.count(), 1);
myText->setMaximumLineCount(2);
myText->setText("This is another heart<img src=\"images/heart200.png\">.");
- QTRY_VERIFY(textPrivate->extra->visibleImgTags.count() == 1);
+ QTRY_COMPARE(textPrivate->extra->visibleImgTags.count(), 1);
// if maximumLineCount is set and the img tag doesn't have an explicit size
// we relayout twice.
- QVERIFY(spy.count() == 3);
+ QCOMPARE(spy.count(), 3);
delete myText;
delete window;
@@ -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..5ec8fa2e83 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);
@@ -573,7 +577,7 @@ void tst_qquicktextedit::textFormat()
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickTextEdit::RichText);
+ QCOMPARE(textObject->textFormat(), QQuickTextEdit::RichText);
}
{
QQmlComponent textComponent(&engine);
@@ -581,7 +585,7 @@ void tst_qquicktextedit::textFormat()
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickTextEdit::PlainText);
+ QCOMPARE(textObject->textFormat(), QQuickTextEdit::PlainText);
}
{
QQmlComponent component(&engine);
@@ -798,7 +802,7 @@ void tst_qquicktextedit::hAlign_RightToLeft()
// keyboard input direction from qApp->inputMethod()->inputDirection
textEdit->setText("");
platformInputContext.setInputDirection(Qt::LeftToRight);
- QVERIFY(qApp->inputMethod()->inputDirection() == Qt::LeftToRight);
+ QCOMPARE(qApp->inputMethod()->inputDirection(), Qt::LeftToRight);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
@@ -806,7 +810,7 @@ void tst_qquicktextedit::hAlign_RightToLeft()
platformInputContext.setInputDirection(Qt::RightToLeft);
QCOMPARE(cursorRectangleSpy.count(), 1);
- QVERIFY(qApp->inputMethod()->inputDirection() == Qt::RightToLeft);
+ QCOMPARE(qApp->inputMethod()->inputDirection(), Qt::RightToLeft);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
@@ -1397,22 +1401,22 @@ void tst_qquicktextedit::selection()
}
textEditObject->setCursorPosition(0);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
+ QCOMPARE(textEditObject->cursorPosition(), 0);
+ QCOMPARE(textEditObject->selectionStart(), 0);
+ QCOMPARE(textEditObject->selectionEnd(), 0);
QVERIFY(textEditObject->selectedText().isNull());
// Verify invalid positions are ignored.
textEditObject->setCursorPosition(-1);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
+ QCOMPARE(textEditObject->cursorPosition(), 0);
+ QCOMPARE(textEditObject->selectionStart(), 0);
+ QCOMPARE(textEditObject->selectionEnd(), 0);
QVERIFY(textEditObject->selectedText().isNull());
textEditObject->setCursorPosition(textEditObject->text().count()+1);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
+ QCOMPARE(textEditObject->cursorPosition(), 0);
+ QCOMPARE(textEditObject->selectionStart(), 0);
+ QCOMPARE(textEditObject->selectionEnd(), 0);
QVERIFY(textEditObject->selectedText().isNull());
//Test selection
@@ -1426,9 +1430,9 @@ void tst_qquicktextedit::selection()
}
textEditObject->setCursorPosition(0);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
+ QCOMPARE(textEditObject->cursorPosition(), 0);
+ QCOMPARE(textEditObject->selectionStart(), 0);
+ QCOMPARE(textEditObject->selectionEnd(), 0);
QVERIFY(textEditObject->selectedText().isNull());
//Test Error Ignoring behaviour
@@ -1443,20 +1447,20 @@ void tst_qquicktextedit::selection()
textEditObject->select(0,100);
QVERIFY(textEditObject->selectedText().isNull());
textEditObject->select(0,10);
- QVERIFY(textEditObject->selectedText().size() == 10);
+ QCOMPARE(textEditObject->selectedText().size(), 10);
textEditObject->select(-10,0);
- QVERIFY(textEditObject->selectedText().size() == 10);
+ QCOMPARE(textEditObject->selectedText().size(), 10);
textEditObject->select(100,101);
- QVERIFY(textEditObject->selectedText().size() == 10);
+ QCOMPARE(textEditObject->selectedText().size(), 10);
textEditObject->select(0,-10);
- QVERIFY(textEditObject->selectedText().size() == 10);
+ QCOMPARE(textEditObject->selectedText().size(), 10);
textEditObject->select(0,100);
- QVERIFY(textEditObject->selectedText().size() == 10);
+ QCOMPARE(textEditObject->selectedText().size(), 10);
textEditObject->deselect();
QVERIFY(textEditObject->selectedText().isNull());
textEditObject->select(0,10);
- QVERIFY(textEditObject->selectedText().size() == 10);
+ QCOMPARE(textEditObject->selectedText().size(), 10);
textEditObject->deselect();
QVERIFY(textEditObject->selectedText().isNull());
}
@@ -1535,31 +1539,31 @@ void tst_qquicktextedit::keySelection()
QSignalSpy spy(input, SIGNAL(selectedTextChanged()));
simulateKey(&window, Qt::Key_Right, Qt::ShiftModifier);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
QCOMPARE(input->selectedText(), QString("a"));
QCOMPARE(spy.count(), 1);
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 2);
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 2);
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
QCOMPARE(spy.count(), 2);
simulateKey(&window, Qt::Key_Left, Qt::ShiftModifier);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
QCOMPARE(input->selectedText(), QString("a"));
QCOMPARE(spy.count(), 3);
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 4);
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 4);
}
@@ -2786,17 +2790,17 @@ void tst_qquicktextedit::navigation()
QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
+ QTRY_VERIFY(input->hasActiveFocus());
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
// Test left and right navigation works if the TextEdit is empty (QTBUG-25447).
input->setText(QString());
@@ -2976,8 +2980,8 @@ void tst_qquicktextedit::readOnly()
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(edit != 0);
- QTRY_VERIFY(edit->hasActiveFocus() == true);
- QVERIFY(edit->isReadOnly() == true);
+ QTRY_VERIFY(edit->hasActiveFocus());
+ QVERIFY(edit->isReadOnly());
QString initial = edit->text();
for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
simulateKey(&window, k);
@@ -3009,7 +3013,7 @@ void tst_qquicktextedit::textInput()
QTest::qWaitForWindowActive(&view);
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
- QVERIFY(edit->hasActiveFocus() == true);
+ QVERIFY(edit->hasActiveFocus());
// test that input method event is committed and change signal is emitted
QSignalSpy spy(edit, SIGNAL(textChanged()));
@@ -3045,7 +3049,7 @@ void tst_qquicktextedit::inputMethodUpdate()
QTest::qWaitForWindowActive(&view);
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
- QVERIFY(edit->hasActiveFocus() == true);
+ QVERIFY(edit->hasActiveFocus());
// text change even without cursor position change needs to trigger update
edit->setText("test");
@@ -3219,15 +3223,15 @@ void tst_qquicktextedit::pastingRichText_QTBUG_14003()
QQuickTextEdit *obj = qobject_cast<QQuickTextEdit*>(component.create());
QTRY_VERIFY(obj != 0);
- QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
+ QTRY_COMPARE(obj->textFormat(), QQuickTextEdit::PlainText);
QMimeData *mData = new QMimeData;
mData->setHtml("<font color=\"red\">Hello</font>");
QGuiApplication::clipboard()->setMimeData(mData);
obj->paste();
- QTRY_VERIFY(obj->text() == "");
- QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
+ QTRY_COMPARE(obj->text(), QString());
+ QTRY_COMPARE(obj->textFormat(), QQuickTextEdit::PlainText);
}
#endif
@@ -3253,11 +3257,11 @@ void tst_qquicktextedit::implicitSize()
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
QVERIFY(textObject->width() < textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
textObject->resetWidth();
- QVERIFY(textObject->width() == textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
}
void tst_qquicktextedit::contentSize()
@@ -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));
+ QCOMPARE(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 d87054ac9e..079f73ae34 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);
@@ -591,7 +593,7 @@ void tst_qquicktextinput::wrap()
textHeight = textObject->height();
QVERIFY(textObject != 0);
- QVERIFY(textObject->wrapMode() == QQuickTextInput::WrapAnywhere);
+ QCOMPARE(textObject->wrapMode(), QQuickTextInput::WrapAnywhere);
QCOMPARE(textObject->width(), 300.);
delete textObject;
@@ -658,22 +660,22 @@ void tst_qquicktextinput::selection()
}
textinputObject->setCursorPosition(0);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
+ QCOMPARE(textinputObject->cursorPosition(), 0);
+ QCOMPARE(textinputObject->selectionStart(), 0);
+ QCOMPARE(textinputObject->selectionEnd(), 0);
QVERIFY(textinputObject->selectedText().isNull());
// Verify invalid positions are ignored.
textinputObject->setCursorPosition(-1);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
+ QCOMPARE(textinputObject->cursorPosition(), 0);
+ QCOMPARE(textinputObject->selectionStart(), 0);
+ QCOMPARE(textinputObject->selectionEnd(), 0);
QVERIFY(textinputObject->selectedText().isNull());
textinputObject->setCursorPosition(textinputObject->text().count()+1);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
+ QCOMPARE(textinputObject->cursorPosition(), 0);
+ QCOMPARE(textinputObject->selectionStart(), 0);
+ QCOMPARE(textinputObject->selectionEnd(), 0);
QVERIFY(textinputObject->selectedText().isNull());
//Test selection
@@ -687,9 +689,9 @@ void tst_qquicktextinput::selection()
}
textinputObject->setCursorPosition(0);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
+ QCOMPARE(textinputObject->cursorPosition(), 0);
+ QCOMPARE(textinputObject->selectionStart(), 0);
+ QCOMPARE(textinputObject->selectionEnd(), 0);
QVERIFY(textinputObject->selectedText().isNull());
//Test Error Ignoring behaviour
@@ -704,20 +706,20 @@ void tst_qquicktextinput::selection()
textinputObject->select(0,100);
QVERIFY(textinputObject->selectedText().isNull());
textinputObject->select(0,10);
- QVERIFY(textinputObject->selectedText().size() == 10);
+ QCOMPARE(textinputObject->selectedText().size(), 10);
textinputObject->select(-10,10);
- QVERIFY(textinputObject->selectedText().size() == 10);
+ QCOMPARE(textinputObject->selectedText().size(), 10);
textinputObject->select(100,101);
- QVERIFY(textinputObject->selectedText().size() == 10);
+ QCOMPARE(textinputObject->selectedText().size(), 10);
textinputObject->select(0,-10);
- QVERIFY(textinputObject->selectedText().size() == 10);
+ QCOMPARE(textinputObject->selectedText().size(), 10);
textinputObject->select(0,100);
- QVERIFY(textinputObject->selectedText().size() == 10);
+ QCOMPARE(textinputObject->selectedText().size(), 10);
textinputObject->deselect();
QVERIFY(textinputObject->selectedText().isNull());
textinputObject->select(0,10);
- QVERIFY(textinputObject->selectedText().size() == 10);
+ QCOMPARE(textinputObject->selectedText().size(), 10);
textinputObject->deselect();
QVERIFY(textinputObject->selectedText().isNull());
@@ -1513,13 +1515,13 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft()
// keyboard input direction from QInputMethod::inputDirection()
textInput->setText("");
platformInputContext.setInputDirection(Qt::LeftToRight);
- QVERIFY(qApp->inputMethod()->inputDirection() == Qt::LeftToRight);
+ QCOMPARE(qApp->inputMethod()->inputDirection(), Qt::LeftToRight);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
QCOMPARE(textInput->boundingRect().left(), qreal(0));
QSignalSpy cursorRectangleSpy(textInput, SIGNAL(cursorRectangleChanged()));
platformInputContext.setInputDirection(Qt::RightToLeft);
- QVERIFY(qApp->inputMethod()->inputDirection() == Qt::RightToLeft);
+ QCOMPARE(qApp->inputMethod()->inputDirection(), Qt::RightToLeft);
QCOMPARE(cursorRectangleSpy.count(), 1);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1);
@@ -1853,7 +1855,7 @@ void tst_qquicktextinput::maxLength()
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
QVERIFY(textinputObject != 0);
QVERIFY(textinputObject->text().isEmpty());
- QVERIFY(textinputObject->maxLength() == 10);
+ QCOMPARE(textinputObject->maxLength(), 10);
foreach (const QString &str, standard) {
QVERIFY(textinputObject->text().length() <= 10);
textinputObject->setText(str);
@@ -1861,7 +1863,7 @@ void tst_qquicktextinput::maxLength()
}
textinputObject->setText("");
- QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
+ QTRY_VERIFY(textinputObject->hasActiveFocus());
for (int i=0; i<20; i++) {
QTRY_COMPARE(textinputObject->text().length(), qMin(i,10));
//simulateKey(&window, Qt::Key_A);
@@ -1880,8 +1882,8 @@ void tst_qquicktextinput::masks()
QVERIFY(window.rootObject() != 0);
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
QVERIFY(textinputObject != 0);
- QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
- QVERIFY(textinputObject->text().length() == 0);
+ QTRY_VERIFY(textinputObject->hasActiveFocus());
+ QCOMPARE(textinputObject->text().length(), 0);
QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
QCOMPARE(textinputObject->length(), 8);
for (int i=0; i<10; i++) {
@@ -1997,7 +1999,7 @@ void tst_qquicktextinput::validators()
QCOMPARE(dblInput->validator()->locale(), defaultLocale);
dblInput->setFocus(true);
- QVERIFY(dblInput->hasActiveFocus() == true);
+ QVERIFY(dblInput->hasActiveFocus());
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
QTest::keyPress(&window, Qt::Key_1);
@@ -2131,7 +2133,7 @@ void tst_qquicktextinput::validators()
QVERIFY(strInput);
QSignalSpy strSpy(strInput, SIGNAL(acceptableInputChanged()));
strInput->setFocus(true);
- QVERIFY(strInput->hasActiveFocus() == true);
+ QVERIFY(strInput->hasActiveFocus());
QCOMPARE(strInput->hasAcceptableInput(), false);
QCOMPARE(strInput->property("acceptable").toBool(), false);
QTest::keyPress(&window, Qt::Key_1);
@@ -2175,7 +2177,7 @@ void tst_qquicktextinput::validators()
QVERIFY(unvalidatedInput);
QSignalSpy unvalidatedSpy(unvalidatedInput, SIGNAL(acceptableInputChanged()));
unvalidatedInput->setFocus(true);
- QVERIFY(unvalidatedInput->hasActiveFocus() == true);
+ QVERIFY(unvalidatedInput->hasActiveFocus());
QCOMPARE(unvalidatedInput->hasAcceptableInput(), true);
QCOMPARE(unvalidatedInput->property("acceptable").toBool(), true);
QTest::keyPress(&window, Qt::Key_1);
@@ -2216,7 +2218,7 @@ void tst_qquicktextinput::inputMethods()
QCOMPARE(plainInput.inputMethodHints(), Qt::ImhNone);
input->setFocus(true);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
// test that input method event is committed
QInputMethodEvent event;
event.setCommitString( "My ", -12, 0);
@@ -2399,23 +2401,23 @@ void tst_qquicktextinput::navigation()
QVERIFY(input != 0);
input->setCursorPosition(0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
+ QTRY_VERIFY(input->hasActiveFocus());
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
//QT-2944: If text is selected, ensure we deselect upon cursor motion
input->setCursorPosition(input->text().length());
input->select(0,input->text().length());
QVERIFY(input->selectionStart() != input->selectionEnd());
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->selectionStart() == input->selectionEnd());
- QVERIFY(input->selectionStart() == input->text().length());
- QVERIFY(input->hasActiveFocus() == true);
+ QCOMPARE(input->selectionStart(), input->selectionEnd());
+ QCOMPARE(input->selectionStart(), input->text().length());
+ QVERIFY(input->hasActiveFocus());
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
// Up and Down should NOT do Home/End, even on OS X (QTBUG-10438).
input->setCursorPosition(2);
@@ -2451,26 +2453,26 @@ void tst_qquicktextinput::navigation_RTL()
input->setText(QString::fromUtf16(arabic_str, 11));
input->setCursorPosition(0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
+ QTRY_VERIFY(input->hasActiveFocus());
// move off
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
// move back
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
input->setCursorPosition(input->text().length());
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
// move off
simulateKey(&window, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
+ QVERIFY(!input->hasActiveFocus());
// move back
simulateKey(&window, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
}
#ifndef QT_NO_CLIPBOARD
@@ -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);
}
@@ -3190,9 +3200,9 @@ void tst_qquicktextinput::readOnly()
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
- QVERIFY(input->isReadOnly() == true);
- QVERIFY(input->isCursorVisible() == false);
+ QTRY_VERIFY(input->hasActiveFocus());
+ QVERIFY(input->isReadOnly());
+ QVERIFY(!input->isCursorVisible());
QString initial = input->text();
for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
simulateKey(&window, k);
@@ -3205,7 +3215,7 @@ void tst_qquicktextinput::readOnly()
input->setReadOnly(false);
QCOMPARE(input->isReadOnly(), false);
QCOMPARE(input->cursorPosition(), input->text().length());
- QVERIFY(input->isCursorVisible() == true);
+ QVERIFY(input->isCursorVisible());
}
void tst_qquicktextinput::echoMode()
@@ -3220,7 +3230,7 @@ void tst_qquicktextinput::echoMode()
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
+ QTRY_VERIFY(input->hasActiveFocus());
QString initial = input->text();
Qt::InputMethodHints ref;
QCOMPARE(initial, QLatin1String("ABCDefgh"));
@@ -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);
+ QVERIFY(!input->hasActiveFocus());
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()
@@ -5819,11 +5830,11 @@ void tst_qquicktextinput::implicitSize()
QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
QVERIFY(textObject->width() < textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
textObject->resetWidth();
- QVERIFY(textObject->width() == textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
}
void tst_qquicktextinput::implicitSizeBinding_data()
@@ -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..2f054e278a 100644
--- a/tests/auto/quick/qquickview/tst_qquickview.cpp
+++ b/tests/auto/quick/qquickview/tst_qquickview.cpp
@@ -184,8 +184,17 @@ void tst_QQuickView::errors()
QQuickView view;
QQmlTestMessageHandler messageHandler;
view.setSource(testFileUrl("error1.qml"));
- QVERIFY(view.status() == QQuickView::Error);
- QVERIFY(view.errors().count() == 1);
+ QCOMPARE(view.status(), QQuickView::Error);
+ QCOMPARE(view.errors().count(), 1);
+ }
+
+ {
+ QQuickView view;
+ QQmlTestMessageHandler messageHandler;
+ view.setSource(testFileUrl("error2.qml"));
+ QCOMPARE(view.status(), QQuickView::Error);
+ QCOMPARE(view.errors().count(), 1);
+ view.show();
}
}
@@ -196,16 +205,16 @@ void tst_QQuickView::engine()
QQuickView *view = new QQuickView(engine, 0);
QVERIFY(view);
- QVERIFY(engine->incubationController() == view->incubationController());
+ QCOMPARE(engine->incubationController(), view->incubationController());
QQuickView *view2 = new QQuickView(engine, 0);
QVERIFY(view);
- QVERIFY(engine->incubationController() == view->incubationController());
+ QCOMPARE(engine->incubationController(), view->incubationController());
delete view;
QVERIFY(!engine->incubationController());
engine->setIncubationController(view2->incubationController());
- QVERIFY(engine->incubationController() == view2->incubationController());
+ QCOMPARE(engine->incubationController(), view2->incubationController());
delete view2;
QVERIFY(!engine->incubationController());
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index 2dd9e77370..d578a0900c 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -513,15 +513,15 @@ void tst_qquickvisualdatamodel::rootIndex()
QVERIFY(obj != 0);
QMetaObject::invokeMethod(obj, "setRoot");
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
+ QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), model.index(0,0));
QMetaObject::invokeMethod(obj, "setRootToParent");
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
+ QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), QModelIndex());
QMetaObject::invokeMethod(obj, "setRoot");
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
+ QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), model.index(0,0));
model.clear(); // will emit modelReset()
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
+ QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), QModelIndex());
delete obj;
}
@@ -628,7 +628,7 @@ void tst_qquickvisualdatamodel::childChanged()
model.item(1,0)->takeRow(1);
name = findItem<QQuickText>(contentItem, "display", 1);
- QVERIFY(name == 0);
+ QVERIFY(!name);
vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
QCOMPARE(listview->count(), 3);
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index dfe5276e8e..e1ea068a62 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());
@@ -978,7 +978,7 @@ void tst_qquickwindow::clearWindow()
delete window;
- QVERIFY(item->window() == 0);
+ QVERIFY(!item->window());
delete item;
}
@@ -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");
@@ -1232,7 +1232,7 @@ void tst_qquickwindow::headless()
if (threaded) {
QTRY_COMPARE(invalidated.size(), 1);
- QVERIFY(window->openglContext() == 0);
+ QVERIFY(!window->openglContext());
}
if (QGuiApplication::platformName() == QLatin1String("windows")
@@ -1242,7 +1242,7 @@ void tst_qquickwindow::headless()
// Destroy the native windowing system buffers
window->destroy();
- QVERIFY(window->handle() == 0);
+ QVERIFY(!window->handle());
// Show and verify that we are back and running
window->show();
@@ -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));
@@ -1609,7 +1609,7 @@ void tst_qquickwindow::hideThenDelete()
if (!persistentGL)
QVERIFY(openglDestroyed->size() > 0);
else
- QVERIFY(openglDestroyed->size() == 0);
+ QCOMPARE(openglDestroyed->size(), 0);
} else {
QCOMPARE(sgInvalidated->size(), 0);
QCOMPARE(openglDestroyed->size(), 0);
@@ -1693,7 +1693,7 @@ void tst_qquickwindow::requestActivate()
window1->requestActivate(); // and then transfer the focus to window1
QTRY_COMPARE(QGuiApplication::focusWindow(), window1.data());
- QVERIFY(window1->isActive() == true);
+ QVERIFY(window1->isActive());
QQuickItem *item = QQuickVisualTestUtil::findItem<QQuickItem>(window1->contentItem(), "item1");
QVERIFY(item);
@@ -1805,7 +1805,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
@@ -1844,7 +1844,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));
@@ -1870,7 +1870,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));
@@ -1899,8 +1899,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));
@@ -1909,6 +1908,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));
@@ -2048,44 +2048,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
@@ -2144,7 +2208,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/qquickxmllistmodel/tst_qquickxmllistmodel.cpp b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
index 5372a4d3b3..c0bf86a212 100644
--- a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
+++ b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
@@ -760,9 +760,9 @@ void tst_qquickxmllistmodel::noKeysValueChanges()
QTRY_VERIFY(model->data(model->index(0, 0), roles.at(2)).toString() != QLatin1String("Football"));
QCOMPARE(model->data(model->index(0, 0), roles.at(2)).toString(), QLatin1String("AussieRules"));
- QVERIFY(spyInsert.count() == 0);
- QVERIFY(spyRemove.count() == 0);
- QVERIFY(spyCount.count() == 0);
+ QCOMPARE(spyInsert.count(), 0);
+ QCOMPARE(spyRemove.count(), 0);
+ QCOMPARE(spyCount.count(), 0);
QCOMPARE(model->rowCount(), 2);
@@ -940,7 +940,7 @@ void tst_qquickxmllistmodel::propertyChanges()
QCOMPARE(model->property("query").toString(), QString("/Pets"));
QCOMPARE(model->property("namespaceDeclarations").toString(), QString("declare namespace media=\"http://search.yahoo.com/mrss/\";"));
- QTRY_VERIFY(model->rowCount() == 1);
+ QTRY_COMPARE(model->rowCount(), 1);
QCOMPARE(sourceSpy.count(),1);
QCOMPARE(xmlSpy.count(),1);
@@ -957,7 +957,7 @@ void tst_qquickxmllistmodel::propertyChanges()
QCOMPARE(modelQuerySpy.count(),1);
QCOMPARE(namespaceDeclarationsSpy.count(),1);
- QTRY_VERIFY(model->rowCount() == 1);
+ QTRY_COMPARE(model->rowCount(), 1);
delete model;
}
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/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 539bbb4703..90ee8215a1 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -863,7 +863,7 @@ void tst_TouchMouse::pinchOnFlickable()
QVERIFY(rect);
// flickable - single touch point
- QVERIFY(flickable->contentX() == 0.0);
+ QCOMPARE(flickable->contentX(), 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
QQuickTouchUtils::flush(window);
@@ -945,7 +945,7 @@ void tst_TouchMouse::flickableOnPinch()
QVERIFY(rect);
// flickable - single touch point
- QVERIFY(flickable->contentX() == 0.0);
+ QCOMPARE(flickable->contentX(), 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
QQuickTouchUtils::flush(window);
@@ -1025,7 +1025,7 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
QVERIFY(rect);
// flickable - single touch point
- QVERIFY(flickable->contentX() == 0.0);
+ QCOMPARE(flickable->contentX(), 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
QQuickTouchUtils::flush(window);
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index 3da920ca27..11696e288f 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -226,8 +226,8 @@ void tst_qquickwidget::errors()
QQmlTestMessageHandler messageHandler;
view->setSource(testFileUrl("error1.qml"));
- QVERIFY(view->status() == QQuickWidget::Error);
- QVERIFY(view->errors().count() == 1);
+ QCOMPARE(view->status(), QQuickWidget::Error);
+ QCOMPARE(view->errors().count(), 1);
}
void tst_qquickwidget::engine()
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 06ed37a00e..90d2a940a3 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;
+ }
#if defined(QT_GUI_LIB) && !defined(QT_NO_OPENGL)
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..7f8c3080c4 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -35,8 +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/qqmlpool_p.h>
+#include <private/qv4value_p.h>
#include <private/qqmlirbuilder_p.h>
#include <QtCore/QCoreApplication>
@@ -199,7 +198,7 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
import[QStringLiteral("classname")] = classnames;
if (plugininfo.contains(QStringLiteral("dependencies"))) {
QStringList dependencies = plugininfo.value(QStringLiteral("dependencies")).toStringList();
- foreach (QString line, dependencies) {
+ foreach (const QString &line, dependencies) {
QList<QString> dep = line.split(QStringLiteral(" "));
QVariantMap depImport;
depImport[QStringLiteral("type")] = QStringLiteral("module");
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..1eab1a0a8c 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,24 +97,26 @@ 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(range(QQmlProfilerDefinitions::RangeType,QQmlProfilerDefinitions::BindingType,qint64,qint64,QStringList,QmlEventLocation)),
+ &m_profilerData, SLOT(addQmlEvent(QQmlProfilerDefinitions::RangeType,QQmlProfilerDefinitions::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,
+ connect(&m_qmlProfilerClient, SIGNAL(sceneGraphFrame(QQmlProfilerDefinitions::SceneGraphFrameType,
qint64,qint64,qint64,qint64,qint64,qint64)),
- &m_profilerData, SLOT(addSceneGraphFrameEvent(QQmlProfilerService::SceneGraphFrameType,
+ &m_profilerData, SLOT(addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType,
qint64,qint64,qint64,qint64,qint64,qint64)));
- connect(&m_qmlProfilerClient, SIGNAL(pixmapCache(QQmlProfilerService::PixmapEventType,qint64,
+ connect(&m_qmlProfilerClient, SIGNAL(pixmapCache(QQmlProfilerDefinitions::PixmapEventType,qint64,
QmlEventLocation,int,int,int)),
- &m_profilerData, SLOT(addPixmapCacheEvent(QQmlProfilerService::PixmapEventType,qint64,
+ &m_profilerData, SLOT(addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType,qint64,
QmlEventLocation,int,int,int)));
- connect(&m_qmlProfilerClient, SIGNAL(memoryAllocation(QQmlProfilerService::MemoryType,qint64,
+ connect(&m_qmlProfilerClient, SIGNAL(memoryAllocation(QQmlProfilerDefinitions::MemoryType,qint64,
qint64)),
- &m_profilerData, SLOT(addMemoryEvent(QQmlProfilerService::MemoryType,qint64,
+ &m_profilerData, SLOT(addMemoryEvent(QQmlProfilerDefinitions::MemoryType,qint64,
qint64)));
+ connect(&m_qmlProfilerClient, SIGNAL(inputEvent(QQmlProfilerDefinitions::EventType,qint64)),
+ &m_profilerData, SLOT(addInputEvent(QQmlProfilerDefinitions::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 < QQmlProfilerDefinitions::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();
}
}
@@ -262,7 +476,8 @@ void QmlProfilerApplication::run()
if (m_runMode == LaunchMode) {
m_process = new QProcess(this);
QStringList arguments;
- arguments << QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_port);
+ arguments << QString::fromLatin1("-qmljsdebugger=port:%1,block,services:CanvasFrameRate")
+ .arg(m_port);
arguments << m_programArguments;
m_process->setProcessChannelMode(QProcess::MergedChannels);
@@ -304,17 +519,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 +541,7 @@ void QmlProfilerApplication::processHasOutput()
{
Q_ASSERT(m_process);
while (m_process->bytesAvailable()) {
- QTextStream out(stdout);
+ QTextStream out(stderr);
out << m_process->readAll();
}
}
@@ -342,19 +549,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 +569,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 +579,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 +633,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 +642,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 e9298f226a..72e11eadec 100644
--- a/tools/qmlprofiler/qmlprofilerclient.cpp
+++ b/tools/qmlprofiler/qmlprofilerclient.cpp
@@ -35,23 +35,19 @@
#include <QtCore/QStack>
#include <QtCore/QStringList>
+#include <QtCore/QDataStream>
#include <limits>
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()
@@ -64,29 +60,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) ||
@@ -101,20 +74,19 @@ class QmlProfilerClientPrivate
{
public:
QmlProfilerClientPrivate()
- : inProgressRanges(0)
- , maximumTime(0)
+ : inProgressRanges(0) , features(std::numeric_limits<quint64>::max())
{
- ::memset(rangeCount, 0,
- QQmlProfilerService::MaximumRangeType * sizeof(int));
+ ::memset(rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int));
}
qint64 inProgressRanges;
- QStack<qint64> rangeStartTimes[QQmlProfilerService::MaximumRangeType];
- QStack<QStringList> rangeDatas[QQmlProfilerService::MaximumRangeType];
- QStack<QmlEventLocation> rangeLocations[QQmlProfilerService::MaximumRangeType];
- QStack<QQmlProfilerService::BindingType> bindingTypes;
- int rangeCount[QQmlProfilerService::MaximumRangeType];
- qint64 maximumTime;
+ QStack<qint64> rangeStartTimes[QQmlProfilerDefinitions::MaximumRangeType];
+ QStack<QStringList> rangeDatas[QQmlProfilerDefinitions::MaximumRangeType];
+ QStack<QmlEventLocation> rangeLocations[QQmlProfilerDefinitions::MaximumRangeType];
+ QStack<QQmlProfilerDefinitions::BindingType> bindingTypes;
+ int rangeCount[QQmlProfilerDefinitions::MaximumRangeType];
+
+ quint64 features;
};
QmlProfilerClient::QmlProfilerClient(
@@ -129,60 +101,91 @@ QmlProfilerClient::~QmlProfilerClient()
delete d;
}
+void QmlProfilerClient::setFeatures(quint64 features)
+{
+ d->features = features;
+}
+
void QmlProfilerClient::clearData()
{
- ::memset(d->rangeCount, 0,
- QQmlProfilerService::MaximumRangeType * sizeof(int));
+ ::memset(d->rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int));
d->bindingTypes.clear();
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 QQmlProfilerDefinitions::ProfileFeature featureFromRangeType(
+ QQmlProfilerDefinitions::RangeType range)
+{
+ switch (range) {
+ case QQmlProfilerDefinitions::Painting:
+ return QQmlProfilerDefinitions::ProfilePainting;
+ case QQmlProfilerDefinitions::Compiling:
+ return QQmlProfilerDefinitions::ProfileCompiling;
+ case QQmlProfilerDefinitions::Creating:
+ return QQmlProfilerDefinitions::ProfileCreating;
+ case QQmlProfilerDefinitions::Binding:
+ return QQmlProfilerDefinitions::ProfileBinding;
+ case QQmlProfilerDefinitions::HandlingSignal:
+ return QQmlProfilerDefinitions::ProfileHandlingSignal;
+ case QQmlProfilerDefinitions::Javascript:
+ return QQmlProfilerDefinitions::ProfileJavaScript;
+ default:
+ return QQmlProfilerDefinitions::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;
stream >> time >> messageType;
- if (messageType >= QQmlProfilerService::MaximumMessage)
+ if (messageType >= QQmlProfilerDefinitions::MaximumMessage)
return;
- if (messageType == QQmlProfilerService::Event) {
+ if (messageType == QQmlProfilerDefinitions::Event) {
int event;
stream >> event;
- if (event == QQmlProfilerService::EndTrace) {
+ if (event == QQmlProfilerDefinitions::EndTrace) {
emit this->traceFinished(time);
- d->maximumTime = time;
- d->maximumTime = qMax(time, d->maximumTime);
- } else if (event == QQmlProfilerService::AnimationFrame) {
+ } else if (event == QQmlProfilerDefinitions::AnimationFrame) {
+ if (!(d->features & one << QQmlProfilerDefinitions::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) {
+ } else if (event == QQmlProfilerDefinitions::StartTrace) {
emit this->traceStarted(time);
- d->maximumTime = time;
- } else if (event < QQmlProfilerService::MaximumEventType) {
- d->maximumTime = qMax(time, d->maximumTime);
+ } else if (event == QQmlProfilerDefinitions::Key ||
+ event == QQmlProfilerDefinitions::Mouse) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileInputEvents))
+ return;
+ emit this->inputEvent((QQmlProfilerDefinitions::EventType)event, time);
}
- } else if (messageType == QQmlProfilerService::Complete) {
+ } else if (messageType == QQmlProfilerDefinitions::Complete) {
emit complete();
- } else if (messageType == QQmlProfilerService::SceneGraphFrame) {
+ } else if (messageType == QQmlProfilerDefinitions::SceneGraphFrame) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileSceneGraph))
+ return;
int sgEventType;
int count = 0;
qint64 params[5];
@@ -193,49 +196,54 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
}
while (count<5)
params[count++] = 0;
- emit sceneGraphFrame((QQmlProfilerService::SceneGraphFrameType)sgEventType, time,
+ emit sceneGraphFrame((QQmlProfilerDefinitions::SceneGraphFrameType)sgEventType, time,
params[0], params[1], params[2], params[3], params[4]);
- d->maximumTime = qMax(time, d->maximumTime);
- } else if (messageType == QQmlProfilerService::PixmapCacheEvent) {
+ } else if (messageType == QQmlProfilerDefinitions::PixmapCacheEvent) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfilePixmapCache))
+ return;
int pixEvTy, width = 0, height = 0, refcount = 0;
QString pixUrl;
stream >> pixEvTy >> pixUrl;
- if (pixEvTy == (int)QQmlProfilerService::PixmapReferenceCountChanged ||
- pixEvTy == (int)QQmlProfilerService::PixmapCacheCountChanged) {
+ if (pixEvTy == (int)QQmlProfilerDefinitions::PixmapReferenceCountChanged ||
+ pixEvTy == (int)QQmlProfilerDefinitions::PixmapCacheCountChanged) {
stream >> refcount;
- } else if (pixEvTy == (int)QQmlProfilerService::PixmapSizeKnown) {
+ } else if (pixEvTy == (int)QQmlProfilerDefinitions::PixmapSizeKnown) {
stream >> width >> height;
refcount = 1;
}
- emit pixmapCache((QQmlProfilerService::PixmapEventType)pixEvTy, time,
+ emit pixmapCache((QQmlProfilerDefinitions::PixmapEventType)pixEvTy, time,
QmlEventLocation(pixUrl,0,0), width, height, refcount);
- d->maximumTime = qMax(time, d->maximumTime);
- } else if (messageType == QQmlProfilerService::MemoryAllocation) {
+ } else if (messageType == QQmlProfilerDefinitions::MemoryAllocation) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileMemory))
+ return;
int type;
qint64 delta;
stream >> type >> delta;
- emit memoryAllocation((QQmlProfilerService::MemoryType)type, time, delta);
- d->maximumTime = qMax(time, d->maximumTime);
+ emit memoryAllocation((QQmlProfilerDefinitions::MemoryType)type, time, delta);
} else {
int range;
stream >> range;
- if (range >= QQmlProfilerService::MaximumRangeType)
+ if (range >= QQmlProfilerDefinitions::MaximumRangeType)
return;
- if (messageType == QQmlProfilerService::RangeStart) {
+ if (!(d->features & one << featureFromRangeType(
+ static_cast<QQmlProfilerDefinitions::RangeType>(range))))
+ return;
+
+ if (messageType == QQmlProfilerDefinitions::RangeStart) {
d->rangeStartTimes[range].push(time);
d->inProgressRanges |= (static_cast<qint64>(1) << range);
++d->rangeCount[range];
// read binding type
- if (range == (int)QQmlProfilerService::Binding) {
- int bindingType = (int)QQmlProfilerService::QmlBinding;
+ if (range == (int)QQmlProfilerDefinitions::Binding) {
+ int bindingType = (int)QQmlProfilerDefinitions::QmlBinding;
if (!stream.atEnd())
stream >> bindingType;
- d->bindingTypes.push((QQmlProfilerService::BindingType)bindingType);
+ d->bindingTypes.push((QQmlProfilerDefinitions::BindingType)bindingType);
}
- } else if (messageType == QQmlProfilerService::RangeData) {
+ } else if (messageType == QQmlProfilerDefinitions::RangeData) {
QString data;
stream >> data;
@@ -246,7 +254,7 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
d->rangeDatas[range][count-1] << data;
}
- } else if (messageType == QQmlProfilerService::RangeLocation) {
+ } else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
QString fileName;
int line;
int column = -1;
@@ -265,17 +273,17 @@ 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() ?
d->rangeLocations[range].pop() : QmlEventLocation();
qint64 startTime = d->rangeStartTimes[range].pop();
- QQmlProfilerService::BindingType bindingType = QQmlProfilerService::QmlBinding;
- if (range == (int)QQmlProfilerService::Binding)
+ QQmlProfilerDefinitions::BindingType bindingType =
+ QQmlProfilerDefinitions::QmlBinding;
+ if (range == (int)QQmlProfilerDefinitions::Binding)
bindingType = d->bindingTypes.pop();
- emit this->range((QQmlProfilerService::RangeType)range,
+ emit this->range((QQmlProfilerDefinitions::RangeType)range,
bindingType, startTime, time - startTime, data, location);
if (d->rangeCount[range] == 0) {
int count = d->rangeDatas[range].count() +
@@ -298,19 +306,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..731ab99973 100644
--- a/tools/qmlprofiler/qmlprofilerclient.h
+++ b/tools/qmlprofiler/qmlprofilerclient.h
@@ -35,8 +35,8 @@
#define QMLPROFILERCLIENT_H
#include "qqmldebugclient.h"
-#include <QtQml/private/qqmlprofilerservice_p.h>
#include "qmlprofilereventlocation.h"
+#include <QtQml/private/qqmlprofilerdefinitions_p.h>
class ProfilerClientPrivate;
class ProfilerClient : public QQmlDebugClient
@@ -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,25 +74,28 @@ public:
QmlProfilerClient(QQmlDebugConnection *client);
~QmlProfilerClient();
+ void setFeatures(quint64 features);
+
public slots:
void clearData();
- void sendRecordingStatus();
+ void sendRecordingStatus(bool record);
signals:
void traceFinished( qint64 time );
void traceStarted( qint64 time );
- void range(QQmlProfilerService::RangeType type,
- QQmlProfilerService::BindingType bindingType,
+ void range(QQmlProfilerDefinitions::RangeType type,
+ QQmlProfilerDefinitions::BindingType bindingType,
qint64 startTime, qint64 length,
const QStringList &data,
const QmlEventLocation &location);
void frame(qint64 time, int frameRate, int animationCount, int threadId);
- void sceneGraphFrame(QQmlProfilerService::SceneGraphFrameType type, qint64 time,
+ void sceneGraphFrame(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time,
qint64 numericData1, qint64 numericData2, qint64 numericData3,
qint64 numericData4, qint64 numericData5);
- void pixmapCache(QQmlProfilerService::PixmapEventType, qint64 time,
+ void pixmapCache(QQmlProfilerDefinitions::PixmapEventType, qint64 time,
const QmlEventLocation &location, int width, int height, int refCount);
- void memoryAllocation(QQmlProfilerService::MemoryType type, qint64 time, qint64 amount);
+ void memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time, qint64 amount);
+ void inputEvent(QQmlProfilerDefinitions::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 76d06cf564..ac7b51159f 100644
--- a/tools/qmlprofiler/qmlprofilerdata.cpp
+++ b/tools/qmlprofiler/qmlprofilerdata.cpp
@@ -74,16 +74,16 @@ struct QmlRangeEventData {
QmlRangeEventData() {} // never called
QmlRangeEventData(const QString &_displayName, int _detailType, const QString &_eventHashStr,
const QmlEventLocation &_location, const QString &_details,
- QQmlProfilerService::Message _message,
- QQmlProfilerService::RangeType _rangeType)
+ QQmlProfilerDefinitions::Message _message,
+ QQmlProfilerDefinitions::RangeType _rangeType)
: displayName(_displayName), eventHashStr(_eventHashStr), location(_location),
details(_details), message(_message), rangeType(_rangeType), detailType(_detailType) {}
QString displayName;
QString eventHashStr;
QmlEventLocation location;
QString details;
- QQmlProfilerService::Message message;
- QQmlProfilerService::RangeType rangeType;
+ QQmlProfilerDefinitions::Message message;
+ QQmlProfilerDefinitions::RangeType rangeType;
int detailType; // can be BindingType, PixmapCacheEventType or SceneGraphFrameType
};
@@ -179,18 +179,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);
@@ -210,7 +210,7 @@ QString QmlProfilerData::getHashStringForV8Event(const QString &displayName, con
return QString(QStringLiteral("%1:%2")).arg(displayName, function);
}
-QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerService::RangeType type)
+QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type)
{
if (type * sizeof(QString) < sizeof(RANGE_TYPE_STRINGS))
return QLatin1String(RANGE_TYPE_STRINGS[type]);
@@ -218,7 +218,7 @@ QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerService::RangeType typ
return QString::number(type);
}
-QString QmlProfilerData::qmlMessageAsString(QQmlProfilerService::Message type)
+QString QmlProfilerData::qmlMessageAsString(QQmlProfilerDefinitions::Message type)
{
if (type * sizeof(QString) < sizeof(MESSAGE_STRINGS))
return QLatin1String(MESSAGE_STRINGS[type]);
@@ -228,12 +228,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
@@ -246,8 +248,8 @@ qint64 QmlProfilerData::traceEndTime() const
return d->traceEndTime;
}
-void QmlProfilerData::addQmlEvent(QQmlProfilerService::RangeType type,
- QQmlProfilerService::BindingType bindingType,
+void QmlProfilerData::addQmlEvent(QQmlProfilerDefinitions::RangeType type,
+ QQmlProfilerDefinitions::BindingType bindingType,
qint64 startTime,
qint64 duration,
const QStringList &data,
@@ -290,7 +292,7 @@ void QmlProfilerData::addQmlEvent(QQmlProfilerService::RangeType type,
newEvent = d->eventDescriptions[eventHashStr];
} else {
newEvent = new QmlRangeEventData(displayName, bindingType, eventHashStr, location, details,
- QQmlProfilerService::MaximumMessage, type);
+ QQmlProfilerDefinitions::MaximumMessage, type);
d->eventDescriptions.insert(eventHashStr, newEvent);
}
@@ -311,11 +313,11 @@ void QmlProfilerData::addFrameEvent(qint64 time, int framerate, int animationcou
if (d->eventDescriptions.contains(eventHashStr)) {
newEvent = d->eventDescriptions[eventHashStr];
} else {
- newEvent = new QmlRangeEventData(displayName, QQmlProfilerService::AnimationFrame,
+ newEvent = new QmlRangeEventData(displayName, QQmlProfilerDefinitions::AnimationFrame,
eventHashStr,
QmlEventLocation(), details,
- QQmlProfilerService::Event,
- QQmlProfilerService::MaximumRangeType);
+ QQmlProfilerDefinitions::Event,
+ QQmlProfilerDefinitions::MaximumRangeType);
d->eventDescriptions.insert(eventHashStr, newEvent);
}
@@ -325,7 +327,10 @@ void QmlProfilerData::addFrameEvent(qint64 time, int framerate, int animationcou
d->startInstanceList.append(rangeEventStartInstance);
}
-void QmlProfilerData::addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time, qint64 numericData1, qint64 numericData2, qint64 numericData3, qint64 numericData4, qint64 numericData5)
+void QmlProfilerData::addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType type,
+ qint64 time, qint64 numericData1, qint64 numericData2,
+ qint64 numericData3, qint64 numericData4,
+ qint64 numericData5)
{
setState(AcquiringData);
@@ -336,8 +341,8 @@ void QmlProfilerData::addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGrap
} else {
newEvent = new QmlRangeEventData(QStringLiteral("<SceneGraph>"), type, eventHashStr,
QmlEventLocation(), QString(),
- QQmlProfilerService::SceneGraphFrame,
- QQmlProfilerService::MaximumRangeType);
+ QQmlProfilerDefinitions::SceneGraphFrame,
+ QQmlProfilerDefinitions::MaximumRangeType);
d->eventDescriptions.insert(eventHashStr, newEvent);
}
@@ -362,8 +367,8 @@ void QmlProfilerData::addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventTy
newEvent = d->eventDescriptions[eventHashStr];
} else {
newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr, location, QString(),
- QQmlProfilerService::PixmapCacheEvent,
- QQmlProfilerService::MaximumRangeType);
+ QQmlProfilerDefinitions::PixmapCacheEvent,
+ QQmlProfilerDefinitions::MaximumRangeType);
d->eventDescriptions.insert(eventHashStr, newEvent);
}
@@ -372,7 +377,7 @@ void QmlProfilerData::addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventTy
d->startInstanceList.append(rangeEventStartInstance);
}
-void QmlProfilerData::addMemoryEvent(QQmlProfilerService::MemoryType type, qint64 time,
+void QmlProfilerData::addMemoryEvent(QQmlProfilerDefinitions::MemoryType type, qint64 time,
qint64 size)
{
setState(AcquiringData);
@@ -382,14 +387,33 @@ void QmlProfilerData::addMemoryEvent(QQmlProfilerService::MemoryType type, qint6
newEvent = d->eventDescriptions[eventHashStr];
} else {
newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr, QmlEventLocation(),
- QString(), QQmlProfilerService::MemoryAllocation,
- QQmlProfilerService::MaximumRangeType);
+ QString(), QQmlProfilerDefinitions::MemoryAllocation,
+ QQmlProfilerDefinitions::MaximumRangeType);
d->eventDescriptions.insert(eventHashStr, newEvent);
}
QmlRangeEventStartInstance rangeEventStartInstance(time, size, 0, 0, 0, 0, newEvent);
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(), QQmlProfilerDefinitions::Event,
+ QQmlProfilerDefinitions::MaximumRangeType);
+ d->eventDescriptions.insert(eventHashStr, newEvent);
+ }
+
+ d->startInstanceList.append(QmlRangeEventStartInstance(time, -1, 0, 0, 0, newEvent));
+}
+
QString QmlProfilerData::rootEventName()
{
return tr("<program>");
@@ -470,7 +494,7 @@ void QmlProfilerData::computeQmlTime()
for (int i = 0; i < d->startInstanceList.count(); i++) {
qint64 st = d->startInstanceList[i].startTime;
- if (d->startInstanceList[i].data->rangeType == QQmlProfilerService::Painting) {
+ if (d->startInstanceList[i].data->rangeType == QQmlProfilerDefinitions::Painting) {
continue;
}
@@ -553,10 +577,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);
@@ -574,9 +606,10 @@ bool QmlProfilerData::save(const QString &filename)
foreach (const QmlRangeEventData *eventData, d->eventDescriptions.values()) {
stream.writeStartElement(QStringLiteral("event"));
- stream.writeAttribute(QStringLiteral("index"), QString::number(d->eventDescriptions.keys().indexOf(eventData->eventHashStr)));
+ stream.writeAttribute(QStringLiteral("index"), QString::number(
+ d->eventDescriptions.keys().indexOf(eventData->eventHashStr)));
stream.writeTextElement(QStringLiteral("displayname"), eventData->displayName);
- if (eventData->rangeType != QQmlProfilerService::MaximumRangeType)
+ if (eventData->rangeType != QQmlProfilerDefinitions::MaximumRangeType)
stream.writeTextElement(QStringLiteral("type"),
qmlRangeTypeAsString(eventData->rangeType));
else
@@ -584,24 +617,37 @@ bool QmlProfilerData::save(const QString &filename)
qmlMessageAsString(eventData->message));
if (!eventData->location.filename.isEmpty()) {
stream.writeTextElement(QStringLiteral("filename"), eventData->location.filename);
- stream.writeTextElement(QStringLiteral("line"), QString::number(eventData->location.line));
- stream.writeTextElement(QStringLiteral("column"), QString::number(eventData->location.column));
+ stream.writeTextElement(QStringLiteral("line"),
+ QString::number(eventData->location.line));
+ stream.writeTextElement(QStringLiteral("column"),
+ QString::number(eventData->location.column));
}
stream.writeTextElement(QStringLiteral("details"), eventData->details);
- if (eventData->rangeType == QQmlProfilerService::Binding)
+ if (eventData->rangeType == QQmlProfilerDefinitions::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 == QQmlProfilerDefinitions::Event) {
+ switch (eventData->detailType) {
+ case QQmlProfilerDefinitions::AnimationFrame:
+ stream.writeTextElement(QStringLiteral("animationFrame"),
+ QString::number((int)eventData->detailType));
+ break;
+ case QQmlProfilerDefinitions::Key:
+ stream.writeTextElement(QStringLiteral("keyEvent"),
+ QString::number((int)eventData->detailType));
+ break;
+ case QQmlProfilerDefinitions::Mouse:
+ stream.writeTextElement(QStringLiteral("mouseEvent"),
+ QString::number((int)eventData->detailType));
+ break;
+ }
+ } else if (eventData->message == QQmlProfilerDefinitions::PixmapCacheEvent)
stream.writeTextElement(QStringLiteral("cacheEventType"),
QString::number((int)eventData->detailType));
- else if (eventData->message == QQmlProfilerService::SceneGraphFrame)
+ else if (eventData->message == QQmlProfilerDefinitions::SceneGraphFrame)
stream.writeTextElement(QStringLiteral("sgEventType"),
QString::number((int)eventData->detailType));
- else if (eventData->message == QQmlProfilerService::MemoryAllocation)
+ else if (eventData->message == QQmlProfilerDefinitions::MemoryAllocation)
stream.writeTextElement(QStringLiteral("memoryEventType"),
QString::number((int)eventData->detailType));
stream.writeEndElement();
@@ -615,26 +661,30 @@ bool QmlProfilerData::save(const QString &filename)
if (event.duration >= 0)
stream.writeAttribute(QStringLiteral("duration"),
QString::number(event.duration));
- stream.writeAttribute(QStringLiteral("eventIndex"), QString::number(d->eventDescriptions.keys().indexOf(event.data->eventHashStr)));
- if (event.data->message == QQmlProfilerService::Event &&
- event.data->detailType == QQmlProfilerService::AnimationFrame) {
+ stream.writeAttribute(QStringLiteral("eventIndex"), QString::number(
+ d->eventDescriptions.keys().indexOf(event.data->eventHashStr)));
+ if (event.data->message == QQmlProfilerDefinitions::Event &&
+ event.data->detailType == QQmlProfilerDefinitions::AnimationFrame) {
// special: animation frame
stream.writeAttribute(QStringLiteral("framerate"), QString::number(event.frameRate));
- stream.writeAttribute(QStringLiteral("animationcount"), QString::number(event.animationCount));
+ stream.writeAttribute(QStringLiteral("animationcount"),
+ QString::number(event.animationCount));
stream.writeAttribute(QStringLiteral("thread"), QString::number(event.threadId));
- } else if (event.data->message == QQmlProfilerService::PixmapCacheEvent) {
+ } else if (event.data->message == QQmlProfilerDefinitions::PixmapCacheEvent) {
// special: pixmap cache event
- if (event.data->detailType == QQmlProfilerService::PixmapSizeKnown) {
+ if (event.data->detailType == QQmlProfilerDefinitions::PixmapSizeKnown) {
stream.writeAttribute(QStringLiteral("width"),
QString::number(event.numericData1));
stream.writeAttribute(QStringLiteral("height"),
QString::number(event.numericData2));
- } else if (event.data->detailType == QQmlProfilerService::PixmapReferenceCountChanged ||
- event.data->detailType == QQmlProfilerService::PixmapCacheCountChanged) {
+ } else if (event.data->detailType ==
+ QQmlProfilerDefinitions::PixmapReferenceCountChanged ||
+ event.data->detailType ==
+ QQmlProfilerDefinitions::PixmapCacheCountChanged) {
stream.writeAttribute(QStringLiteral("refCount"),
QString::number(event.numericData3));
}
- } else if (event.data->message == QQmlProfilerService::SceneGraphFrame) {
+ } else if (event.data->message == QQmlProfilerDefinitions::SceneGraphFrame) {
// special: scenegraph frame events
if (event.numericData1 > 0)
stream.writeAttribute(QStringLiteral("timing1"),
@@ -651,7 +701,7 @@ bool QmlProfilerData::save(const QString &filename)
if (event.numericData5 > 0)
stream.writeAttribute(QStringLiteral("timing5"),
QString::number(event.numericData5));
- } else if (event.data->message == QQmlProfilerService::MemoryAllocation) {
+ } else if (event.data->message == QQmlProfilerDefinitions::MemoryAllocation) {
stream.writeAttribute(QStringLiteral("amount"), QString::number(event.numericData1));
}
stream.writeEndElement();
@@ -662,7 +712,8 @@ bool QmlProfilerData::save(const QString &filename)
stream.writeAttribute(QStringLiteral("totalTime"), QString::number(d->v8MeasuredTime));
foreach (QV8EventInfo *v8event, d->v8EventHash.values()) {
stream.writeStartElement(QStringLiteral("event"));
- stream.writeAttribute(QStringLiteral("index"), QString::number(d->v8EventHash.keys().indexOf(v8event->eventHashStr)));
+ stream.writeAttribute(QStringLiteral("index"),QString::number(
+ d->v8EventHash.keys().indexOf(v8event->eventHashStr)));
stream.writeTextElement(QStringLiteral("displayname"), v8event->displayName);
stream.writeTextElement(QStringLiteral("functionname"), v8event->functionName);
if (!v8event->fileName.isEmpty()) {
@@ -681,7 +732,8 @@ bool QmlProfilerData::save(const QString &filename)
}
stream.writeAttribute(QStringLiteral("list"), childrenIndexes.join(QString(", ")));
- stream.writeAttribute(QStringLiteral("childrenTimes"), childrenTimes.join(QString(", ")));
+ stream.writeAttribute(QStringLiteral("childrenTimes"),
+ childrenTimes.join(QString(", ")));
stream.writeEndElement();
}
stream.writeEndElement();
diff --git a/tools/qmlprofiler/qmlprofilerdata.h b/tools/qmlprofiler/qmlprofilerdata.h
index d420275d5e..91c16c3222 100644
--- a/tools/qmlprofiler/qmlprofilerdata.h
+++ b/tools/qmlprofiler/qmlprofilerdata.h
@@ -34,9 +34,9 @@
#ifndef QMLPROFILERDATA_H
#define QMLPROFILERDATA_H
-#include <QtQml/private/qqmlprofilerservice_p.h>
#include "qmlprofilereventlocation.h"
+#include <QtQml/private/qqmlprofilerdefinitions_p.h>
#include <QObject>
class QmlProfilerDataPrivate;
@@ -56,8 +56,8 @@ public:
static QString getHashStringForQmlEvent(const QmlEventLocation &location, int eventType);
static QString getHashStringForV8Event(const QString &displayName, const QString &function);
- static QString qmlRangeTypeAsString(QQmlProfilerService::RangeType type);
- static QString qmlMessageAsString(QQmlProfilerService::Message type);
+ static QString qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type);
+ static QString qmlMessageAsString(QQmlProfilerDefinitions::Message type);
static QString rootEventName();
static QString rootEventDescription();
@@ -75,19 +75,20 @@ public slots:
void clear();
void setTraceEndTime(qint64 time);
void setTraceStartTime(qint64 time);
- void addQmlEvent(QQmlProfilerService::RangeType type,
- QQmlProfilerService::BindingType bindingType,
+ void addQmlEvent(QQmlProfilerDefinitions::RangeType type,
+ QQmlProfilerDefinitions::BindingType bindingType,
qint64 startTime, qint64 duration, const QStringList &data,
const QmlEventLocation &location);
void addV8Event(int depth, const QString &function, const QString &filename,
int lineNumber, double totalTime, double selfTime);
void addFrameEvent(qint64 time, int framerate, int animationcount, int threadId);
- void addSceneGraphFrameEvent(QQmlProfilerService::SceneGraphFrameType type, qint64 time,
+ void addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time,
qint64 numericData1, qint64 numericData2, qint64 numericData3,
qint64 numericData4, qint64 numericData5);
- void addPixmapCacheEvent(QQmlProfilerService::PixmapEventType type, qint64 time,
+ void addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time,
const QmlEventLocation &location, int width, int height, int refcount);
- void addMemoryEvent(QQmlProfilerService::MemoryType type, qint64 time, qint64 size);
+ void addMemoryEvent(QQmlProfilerDefinitions::MemoryType type, qint64 time, qint64 size);
+ void addInputEvent(QQmlProfilerDefinitions::EventType type, qint64 time);
void complete();
bool save(const QString &filename);