aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/examples/tutorial.qdoc34
-rw-r--r--examples/demos/samegame/content/Button.qml3
-rw-r--r--examples/demos/samegame/content/NameInputDialog.qml2
-rwxr-xr-xexamples/demos/samegame/content/samegame.js2
-rw-r--r--examples/demos/samegame/main.cpp65
-rw-r--r--examples/demos/samegame/samegame-desktop.qml (renamed from examples/demos/samegame/samegame.qml)0
-rw-r--r--examples/demos/samegame/samegame-mobile.qml83
-rw-r--r--examples/demos/samegame/samegame.pro9
-rw-r--r--examples/demos/samegame/samegame.qdoc38
-rw-r--r--examples/demos/samegame/samegame.qmlproject2
-rw-r--r--examples/quick/accessibility/content/Checkbox.qml (renamed from examples/declarative/accessibility/widgets/Checkbox.qml)0
-rw-r--r--examples/quick/accessibility/content/Slider.qml (renamed from examples/declarative/accessibility/widgets/Slider.qml)0
-rw-r--r--examples/quick/keyinteraction/keyinteraction.pro10
-rw-r--r--examples/quick/keyinteraction/keyinteraction.qml58
-rw-r--r--examples/quick/keyinteraction/keyinteraction.qmlproject16
-rw-r--r--examples/quick/keyinteraction/main.cpp41
-rw-r--r--examples/quick/modelviews/listview/dynamiclist.qml121
-rw-r--r--examples/quick/modelviews/listview/highlight.qml4
-rw-r--r--examples/quick/modelviews/listview/highlightranges.qml56
-rw-r--r--examples/quick/modelviews/main.cpp41
-rw-r--r--examples/quick/modelviews/modelviews.pro20
-rw-r--r--examples/quick/modelviews/modelviews.qml51
-rw-r--r--examples/quick/modelviews/package/Delegate.qml18
-rw-r--r--examples/quick/modelviews/package/view.qml22
-rw-r--r--examples/quick/modelviews/parallax/parallax.qml2
-rw-r--r--examples/quick/modelviews/visualdatamodel/sortedmodel.qml141
-rw-r--r--examples/quick/mousearea/main.cpp41
-rw-r--r--examples/quick/mousearea/mousearea.pro10
-rw-r--r--examples/quick/mousearea/mousearea.qml (renamed from examples/quick/mousearea/mousearea-example.qml)11
-rw-r--r--examples/quick/mousearea/mousearea.qmlproject16
-rw-r--r--examples/quick/openglunderqml/main.cpp2
-rw-r--r--examples/quick/openglunderqml/main.qml7
-rw-r--r--examples/quick/painteditem/smile/smile.qml110
-rw-r--r--examples/quick/painteditem/textballoons/textballoons.qml11
-rw-r--r--examples/quick/quick.pro4
-rw-r--r--examples/quick/threading/main.cpp41
-rw-r--r--examples/quick/threading/threading.pro10
-rw-r--r--examples/quick/threading/threading.qml66
-rw-r--r--examples/quick/threading/threading.qmlproject16
-rw-r--r--examples/quick/threading/workerscript/Spinner.qml87
-rw-r--r--examples/quick/threading/workerscript/workerscript.js31
-rw-r--r--examples/quick/threading/workerscript/workerscript.qml56
-rw-r--r--examples/quick/touchinteraction/flickable/basic-flickable.qml68
-rw-r--r--examples/quick/touchinteraction/flickable/content/Panel.qml (renamed from examples/quick/touchinteraction/flickable/content/Day.qml)2
-rw-r--r--examples/quick/touchinteraction/flickable/corkboards.qml51
-rw-r--r--examples/quick/touchinteraction/main.cpp41
-rw-r--r--examples/quick/touchinteraction/multipointtouch/bearwhack.qml2
-rw-r--r--examples/quick/touchinteraction/multipointtouch/content/title.pngbin81252 -> 76246 bytes
-rw-r--r--examples/quick/touchinteraction/touchinteraction.pro10
-rw-r--r--examples/quick/touchinteraction/touchinteraction.qml21
-rw-r--r--examples/tutorials/helloworld/tutorial1.qml2
-rw-r--r--examples/tutorials/helloworld/tutorial2.qml2
-rw-r--r--examples/tutorials/helloworld/tutorial3.qml2
-rw-r--r--src/3rdparty/javascriptcore/DateMath.cpp7
-rw-r--r--src/imports/folderlistmodel/folderlistmodel.pro2
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp8
-rw-r--r--src/plugins/accessible/shared/qqmlaccessible.cpp6
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp3
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro8
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp19
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h2
-rw-r--r--src/plugins/qmltooling/shared/qpacketprotocol.cpp (renamed from src/qml/debugger/qpacketprotocol.cpp)2
-rw-r--r--src/plugins/qmltooling/shared/qpacketprotocol.h (renamed from src/qml/debugger/qpacketprotocol_p.h)24
-rw-r--r--src/qml/debugger/debugger.pri2
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp35
-rw-r--r--src/qml/debugger/qqmldebugserverconnection_p.h2
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp86
-rw-r--r--src/qml/debugger/qqmlenginedebugservice_p.h6
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h59
-rw-r--r--src/qml/debugger/qv8debugservice.cpp2
-rw-r--r--src/qml/debugger/qv8profilerservice.cpp21
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h4
-rw-r--r--src/qml/qml/ftw/qqmlpool.cpp4
-rw-r--r--src/qml/qml/qqmlaccessors_p.h4
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp13
-rw-r--r--src/qml/qml/qqmlcompiler.cpp18
-rw-r--r--src/qml/qml/qqmlcomponent.cpp10
-rw-r--r--src/qml/qml/qqmlcontext_p.h2
-rw-r--r--src/qml/qml/qqmldirparser.cpp14
-rw-r--r--src/qml/qml/qqmldirparser_p.h3
-rw-r--r--src/qml/qml/qqmlextensionplugin.cpp2
-rw-r--r--src/qml/qml/qqmlimport.cpp28
-rw-r--r--src/qml/qml/qqmlimport_p.h2
-rw-r--r--src/qml/qml/qqmlincubator.cpp3
-rw-r--r--src/qml/qml/qqmlmetatype.cpp4
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp25
-rw-r--r--src/qml/qml/qqmlstringconverters.cpp3
-rw-r--r--src/qml/qml/qqmltypeloader.cpp41
-rw-r--r--src/qml/qml/qqmltypeloader_p.h1
-rw-r--r--src/qml/qml/qqmlvme.cpp2
-rw-r--r--src/qml/qml/qqmlwatcher.cpp5
-rw-r--r--src/qml/qml/qqmlwatcher_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp2
-rw-r--r--src/qml/qml/v4/qv4bindings.cpp19
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp10
-rw-r--r--src/qml/qml/v4/qv4instruction.cpp6
-rw-r--r--src/qml/qml/v4/qv4instruction_p.h2
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp4
-rw-r--r--src/qml/qml/v8/qjsconverter_impl_p.h4
-rw-r--r--src/qml/qml/v8/qjsvalue.cpp2
-rw-r--r--src/qml/qml/v8/qjsvalue_impl_p.h2
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp45
-rw-r--r--src/qml/qml/v8/qv8engine.cpp7
-rw-r--r--src/qmldevtools/qmldevtools.pro2
-rw-r--r--src/qmltest/qmltest.pro2
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp4
-rw-r--r--src/quick/items/qquickaccessibleattached.cpp4
-rw-r--r--src/quick/items/qquickaccessibleattached_p.h8
-rw-r--r--src/quick/items/qquickcanvas.cpp166
-rw-r--r--src/quick/items/qquickcanvas.h6
-rw-r--r--src/quick/items/qquickcanvas_p.h7
-rw-r--r--src/quick/items/qquickflickable.cpp50
-rw-r--r--src/quick/items/qquickitem.cpp299
-rw-r--r--src/quick/items/qquickitem.h1
-rw-r--r--src/quick/items/qquickitem_p.h14
-rw-r--r--src/quick/items/qquickitemanimation.cpp2
-rw-r--r--src/quick/items/qquickitemview.cpp12
-rw-r--r--src/quick/items/qquickloader.cpp12
-rw-r--r--src/quick/items/qquickpathview.cpp3
-rw-r--r--src/quick/items/qquickshadereffect.cpp57
-rw-r--r--src/quick/items/qquickshadereffect_p.h3
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp14
-rw-r--r--src/quick/items/qquickshadereffectnode_p.h2
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp108
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h7
-rw-r--r--src/quick/items/qquicksprite.cpp12
-rw-r--r--src/quick/items/qquickspriteengine.cpp4
-rw-r--r--src/quick/items/qquickspriteengine_p.h2
-rw-r--r--src/quick/items/qquickspriteimage.cpp2
-rw-r--r--src/quick/items/qquicktext.cpp51
-rw-r--r--src/quick/items/qquicktextcontrol.cpp127
-rw-r--r--src/quick/items/qquicktextcontrol_p.h23
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h4
-rw-r--r--src/quick/items/qquicktextedit.cpp18
-rw-r--r--src/quick/items/qquicktextedit_p_p.h3
-rw-r--r--src/quick/items/qquicktextinput.cpp110
-rw-r--r--src/quick/items/qquicktextinput_p_p.h7
-rw-r--r--src/quick/items/qquickvisualadaptormodel.cpp3
-rw-r--r--src/quick/items/qquickwindowmanager.cpp8
-rw-r--r--src/quick/particles/qquickangledirection.cpp3
-rw-r--r--src/quick/particles/qquickcustomparticle.cpp6
-rw-r--r--src/quick/particles/qquickcustomparticle_p.h2
-rw-r--r--src/quick/particles/qquickellipseextruder.cpp5
-rw-r--r--src/quick/particles/qquickimageparticle.cpp7
-rw-r--r--src/quick/particles/qquickimageparticle_p.h2
-rw-r--r--src/quick/particles/qquickparticleemitter.cpp6
-rw-r--r--src/quick/particles/qquickparticlepainter.cpp15
-rw-r--r--src/quick/particles/qquickparticlepainter_p.h7
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp4
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp191
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h108
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp140
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h5
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp107
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h161
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp76
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp28
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h17
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h16
-rw-r--r--src/quick/scenegraph/scenegraph.pri2
-rw-r--r--src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp177
-rw-r--r--src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h142
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil.cpp31
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil_p.h10
-rw-r--r--src/quick/util/qquickpath.cpp2
-rw-r--r--src/quick/util/qquickpathinterpolator.cpp2
-rw-r--r--tests/auto/qml/debugger/debugger.pro10
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro2
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro2
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro5
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp1
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml4
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp24
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro6
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp5
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp460
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.h237
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro8
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp1002
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/app/app.pro1
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp113
-rw-r--r--tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro2
-rw-r--r--tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp36
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.cpp17
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.pri7
-rw-r--r--tests/auto/qml/debugger/shared/debugutil_p.h15
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugclient.cpp3
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugclient.h3
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp58
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.h62
-rw-r--r--tests/auto/qml/debugger/shared/qqmlenginedebug.cpp1068
-rw-r--r--tests/auto/qml/debugger/shared/qqmlenginedebug_p.h388
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp4
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignDate.2.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignDate.3.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignDate.4.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignDate.5.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignDate.6.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignDate.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/componentCreation.qml52
-rw-r--r--tests/auto/qml/qqmlecmascript/data/enums.3.qml41
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js5
-rw-r--r--tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js5
-rw-r--r--tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml21
-rw-r--r--tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp223
-rw-r--r--tests/auto/qml/qqmlerror/.gitattributes1
-rw-r--r--tests/auto/qml/qqmllanguage/data/globalEnums.qml55
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp5
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h93
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp61
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/.gitattributes3
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro2
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp2
-rw-r--r--tests/auto/qml/v4/data/objectToBool.qml16
-rw-r--r--tests/auto/qml/v4/tst_v4.cpp1
-rw-r--r--tests/auto/qmltest/animatedimage/stickman.gifbin0 -> 164923 bytes
-rw-r--r--tests/auto/qmltest/animatedimage/tst_animatedimage.qml220
-rw-r--r--tests/auto/qmltest/borderimage/remote.sci7
-rw-r--r--tests/auto/qmltest/borderimage/tst_borderimage.qml68
-rw-r--r--tests/auto/qmltest/fontloader/dummy.ttf0
-rw-r--r--tests/auto/qmltest/fontloader/tarzeau_ocr_a.ttfbin0 -> 24544 bytes
-rw-r--r--tests/auto/qmltest/fontloader/tst_fontloader.qml97
-rw-r--r--tests/auto/qmltest/gradient/tst_gradient.qml119
-rw-r--r--tests/auto/qmltest/image/logo.pngbin0 -> 1478 bytes
-rw-r--r--tests/auto/qmltest/image/tst_image.qml216
-rw-r--r--tests/auto/qmltest/listmodel/tst_listmodel.qml132
-rw-r--r--tests/auto/qmltest/listview/tst_listview.qml175
-rw-r--r--tests/auto/qmltest/rectangle/tst_rectangle.qml137
-rw-r--r--tests/auto/qmltest/text/tst_text.qml120
-rw-r--r--tests/auto/qmltest/textedit/tst_textedit.qml165
-rw-r--r--tests/auto/qmltest/textinput/tst_textinput.qml286
-rw-r--r--tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml26
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp24
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_arc.qml1
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml1
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_path.qml1
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml1
-rw-r--r--tests/auto/quick/qquickflickable/data/cancel.qml15
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp51
-rw-r--r--tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp21
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp23
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp80
-rw-r--r--tests/auto/quick/qquickitemlayer/data/Effect.qml8
-rw-r--r--tests/auto/quick/qquickitemlayer/data/SourceRect.qml4
-rw-r--r--tests/auto/quick/qquickitemlayer/data/TextureProvider.qml8
-rw-r--r--tests/auto/quick/qquicklistview/data/margins2.qml4
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp31
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp6
-rw-r--r--tests/auto/quick/qquickpathview/data/dragpath.qml1
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp36
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp74
-rw-r--r--tests/auto/quick/qquicktextedit/data/mouseselection_true.qml2
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp311
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp953
-rw-r--r--tests/system/sys_listview.qtt221
-rw-r--r--tests/testapplications/listview/alteredViews.qml153
-rw-r--r--tests/testapplications/listview/onRemove.qml156
-rw-r--r--tests/testapplications/listview/star.pngbin0 -> 1550 bytes
-rw-r--r--tests/testapplications/listview/viewTransitions.qml479
-rw-r--r--tools/easingcurveeditor/easingcurveeditor.pro2
-rw-r--r--tools/qmlplugindump/qmlplugindump.pro6
-rw-r--r--tools/qmlprofiler/qmlprofiler.pro8
-rw-r--r--tools/qmlprofiler/qpacketprotocol.cpp546
-rw-r--r--tools/qmlprofiler/qpacketprotocol.h117
-rw-r--r--tools/qmlprofiler/qqmldebugclient.cpp3
-rw-r--r--tools/qmlscene/main.cpp9
278 files changed, 9996 insertions, 3921 deletions
diff --git a/doc/src/examples/tutorial.qdoc b/doc/src/examples/tutorial.qdoc
index d8d6e14f09..558b5bb6d9 100644
--- a/doc/src/examples/tutorial.qdoc
+++ b/doc/src/examples/tutorial.qdoc
@@ -41,7 +41,7 @@ with properties and signals, and we will create a simple animation with the help
Chapter one starts with a minimal "Hello world" program and the following chapters introduce new concepts.
-The tutorial's source code is located in the $QTDIR/examples/declarative/tutorials/helloworld directory.
+The tutorial's source code is located in the $QTDIR/examples/tutorials/helloworld directory.
Tutorial chapters:
@@ -68,7 +68,7 @@ The picture below is a screenshot of this program.
Here is the QML code for the application:
-\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 0
+\snippet examples/tutorials/helloworld/tutorial1.qml 0
\section1 Walkthrough
@@ -77,11 +77,11 @@ Here is the QML code for the application:
First, we need to import the types that we need for this example. Most QML files will import the built-in QML
types (like \l{Rectangle}, \l{Image}, ...) that come with Qt, using:
-\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 3
+\snippet examples/tutorials/helloworld/tutorial1.qml 3
\section2 Rectangle element
-\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 1
+\snippet examples/tutorials/helloworld/tutorial1.qml 1
We declare a root element of type \l{Rectangle}. It is one of the basic building blocks you can use to create an application in QML.
We give it an \c{id} to be able to refer to it later. In this case, we call it "page".
@@ -90,7 +90,7 @@ The \l{Rectangle} element contains many other properties (such as \c x and \c y)
\section2 Text element
-\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 2
+\snippet examples/tutorials/helloworld/tutorial1.qml 2
We add a \l Text element as a child of the root Rectangle element that displays the text 'Hello world!'.
@@ -108,7 +108,7 @@ To view what you have created, run the \l{QML Viewer} tool (located in the \c bi
For example, to run the provided completed Tutorial 1 example from the install location, you would type:
\code
-bin/qmlviewer $QTDIR/examples/declarative/tutorials/helloworld/tutorial1.qml
+bin/qmlviewer $QTDIR/examples/tutorials/helloworld/tutorial1.qml
\endcode
*/
@@ -133,37 +133,37 @@ The component's filename must always start with a capital letter.
Here is the QML code for \c Cell.qml:
-\snippet examples/declarative/tutorials/helloworld/Cell.qml 0
+\snippet examples/tutorials/helloworld/Cell.qml 0
\section1 Walkthrough
\section2 The Cell Component
-\snippet examples/declarative/tutorials/helloworld/Cell.qml 1
+\snippet examples/tutorials/helloworld/Cell.qml 1
The root element of our component is an \l Item with the \c id \e container.
An \l Item is the most basic visual element in QML and is often used as a container for other elements.
-\snippet examples/declarative/tutorials/helloworld/Cell.qml 4
+\snippet examples/tutorials/helloworld/Cell.qml 4
We declare a \c cellColor property. This property is accessible from \e outside our component, this allows us
to instantiate the cells with different colors.
This property is just an alias to an existing property - the color of the rectangle that compose the cell
(see \l{Property Binding in QML}).
-\snippet examples/declarative/tutorials/helloworld/Cell.qml 5
+\snippet examples/tutorials/helloworld/Cell.qml 5
We want our component to also have a signal that we call \e clicked with a \e cellColor parameter of type \e color.
We will use this signal to change the color of the text in the main QML file later.
-\snippet examples/declarative/tutorials/helloworld/Cell.qml 2
+\snippet examples/tutorials/helloworld/Cell.qml 2
Our cell component is basically a colored rectangle with the \c id \e rectangle.
The \c anchors.fill property is a convenient way to set the size of an element.
In this case the rectangle will have the same size as its parent (see \l{anchor-layout}{Anchor-Based Layout}).
-\snippet examples/declarative/tutorials/helloworld/Cell.qml 3
+\snippet examples/tutorials/helloworld/Cell.qml 3
In order to change the color of the text when clicking on a cell, we create a \l MouseArea element with
the same size as its parent.
@@ -175,11 +175,11 @@ When this signal is triggered we want to emit our own \e clicked signal with the
In our main QML file, we use our \c Cell component to create the color picker:
-\snippet examples/declarative/tutorials/helloworld/tutorial2.qml 0
+\snippet examples/tutorials/helloworld/tutorial2.qml 0
We create the color picker by putting 6 cells with different colors in a grid.
-\snippet examples/declarative/tutorials/helloworld/tutorial2.qml 1
+\snippet examples/tutorials/helloworld/tutorial2.qml 1
When the \e clicked signal of our cell is triggered, we want to set the color of the text to the \e cellColor passed as a parameter.
We can react to any signal of our component through a property of the name \e 'onSignalName' (see \l{Signal Handlers}).
@@ -200,11 +200,11 @@ We want our text to move to the bottom of the screen, rotate and become red when
Here is the QML code:
-\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 0
+\snippet examples/tutorials/helloworld/tutorial3.qml 0
\section1 Walkthrough
-\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 2
+\snippet examples/tutorials/helloworld/tutorial3.qml 2
First, we create a new \e down state for our text element.
This state will be activated when the \l MouseArea is pressed, and deactivated when it is released.
@@ -213,7 +213,7 @@ The \e down state includes a set of property changes from our implicit \e {defau
(the items as they were initially defined in the QML).
Specifically, we set the \c y property of the text to \c 160, the rotation to \c 180 and the \c color to red.
-\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 3
+\snippet examples/tutorials/helloworld/tutorial3.qml 3
Because we don't want the text to appear at the bottom instantly but rather move smoothly,
we add a transition between our two states.
diff --git a/examples/demos/samegame/content/Button.qml b/examples/demos/samegame/content/Button.qml
index 2d1a993226..44da525144 100644
--- a/examples/demos/samegame/content/Button.qml
+++ b/examples/demos/samegame/content/Button.qml
@@ -45,6 +45,7 @@ Rectangle {
id: container
property string text: "Button"
+ property int fontSize: 24
signal clicked
@@ -70,6 +71,6 @@ Rectangle {
MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() }
Text {
- id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText; font.pixelSize: 24
+ id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText; font.pixelSize: container.fontSize
}
}
diff --git a/examples/demos/samegame/content/NameInputDialog.qml b/examples/demos/samegame/content/NameInputDialog.qml
index 7c3bfa274a..26101d6645 100644
--- a/examples/demos/samegame/content/NameInputDialog.qml
+++ b/examples/demos/samegame/content/NameInputDialog.qml
@@ -62,7 +62,7 @@ Dialog {
Text {
id: dialogText
anchors { left: nameInputDialog.left; leftMargin: 20; verticalCenter: parent.verticalCenter }
- text: "You won! Please enter your name: "
+ text: "You won! Your name: "
}
MouseArea {
anchors.fill: parent
diff --git a/examples/demos/samegame/content/samegame.js b/examples/demos/samegame/content/samegame.js
index 611767584b..d530718927 100755
--- a/examples/demos/samegame/content/samegame.js
+++ b/examples/demos/samegame/content/samegame.js
@@ -173,7 +173,7 @@ function victoryCheck()
}
initHighScoreBar();
if(gameCanvas.score > highScoreBar){
- nameInputDialog.show("You won! Please enter your name: ");
+ nameInputDialog.show("You won! Your name: ");
nameInputDialog.initialWidth = nameInputDialog.text.width + 20;
if (nameInputDialog.name == "")
nameInputDialog.width = nameInputDialog.initialWidth;
diff --git a/examples/demos/samegame/main.cpp b/examples/demos/samegame/main.cpp
new file mode 100644
index 0000000000..4a0f88ae70
--- /dev/null
+++ b/examples/demos/samegame/main.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QStringList>
+#include <QQuickView>
+#include <QQmlEngine>
+
+void usage()
+{
+ printf("Pass -desktop to use the Desktop UI. Default is the mobile UI.");
+ exit(0);
+}
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc,argv);
+ QQuickView view;
+ QUrl launchFile = QUrl::fromLocalFile(QLatin1String("samegame-mobile.qml"));
+ if (app.arguments().contains(QLatin1String("-help")))
+ usage();
+ if (app.arguments().contains(QLatin1String("-desktop")))
+ launchFile = QUrl::fromLocalFile(QLatin1String("samegame-desktop.qml"));
+ view.setSource(launchFile);
+ view.show();
+ return app.exec();
+}
+
diff --git a/examples/demos/samegame/samegame.qml b/examples/demos/samegame/samegame-desktop.qml
index b98b6a0074..b98b6a0074 100644
--- a/examples/demos/samegame/samegame.qml
+++ b/examples/demos/samegame/samegame-desktop.qml
diff --git a/examples/demos/samegame/samegame-mobile.qml b/examples/demos/samegame/samegame-mobile.qml
new file mode 100644
index 0000000000..04555a8f25
--- /dev/null
+++ b/examples/demos/samegame/samegame-mobile.qml
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Particles 2.0
+import "content"
+import "content/samegame.js" as Logic
+
+Rectangle {
+ id: screen
+ width: 320; height: 480
+
+ SystemPalette { id: activePalette }
+
+ GameArea {
+ id: gameCanvas
+ width: parent.width
+ blockSize: 40
+ anchors { top: parent.top; bottom: toolBar.top }
+ }
+
+ Rectangle {
+ id: toolBar
+ width: parent.width; height: 40
+ color: activePalette.window
+ anchors.bottom: screen.bottom
+
+ Button {
+ id: newGameButton
+ anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter }
+ fontSize: 12
+ text: "New Game"
+ onClicked: Logic.startNewGame(gameCanvas)
+ }
+
+ Text {
+ id: score
+ anchors { right: parent.right; rightMargin: 12; verticalCenter: parent.verticalCenter }
+ text: "Score: " + gameCanvas.score
+ font.bold: true
+ font.pixelSize: 12
+ color: activePalette.windowText
+ }
+ }
+}
diff --git a/examples/demos/samegame/samegame.pro b/examples/demos/samegame/samegame.pro
new file mode 100644
index 0000000000..4f9a295dc4
--- /dev/null
+++ b/examples/demos/samegame/samegame.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+
+QT += qml
+SOURCES += main.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/demos/samegame
+qml.files = samegame-desktop.qml samegame-mobile.qml content
+qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/demos/samegame
+INSTALLS += target qml
diff --git a/examples/demos/samegame/samegame.qdoc b/examples/demos/samegame/samegame.qdoc
new file mode 100644
index 0000000000..7a311600c6
--- /dev/null
+++ b/examples/demos/samegame/samegame.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** GNU Free Documentation License
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms
+** and conditions contained in a signed written agreement between you
+** and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \title QML Demo - SameGame
+ \example demos/samegame
+ \brief This is an example game written in QML.
+ \image qml-samegame-demo-small.png
+
+ The SameGame demo implements a simple game in QML. It is written for desktop and portrait devices.
+
+ This game has the logic implemented in Javascipt and the appearance implemented in QML.
+*/
+
diff --git a/examples/demos/samegame/samegame.qmlproject b/examples/demos/samegame/samegame.qmlproject
index 42ffacf4f8..e0f1074913 100644
--- a/examples/demos/samegame/samegame.qmlproject
+++ b/examples/demos/samegame/samegame.qmlproject
@@ -1,7 +1,7 @@
import QmlProject 1.1
Project {
- mainFile: "samegame.qml"
+ mainFile: "samegame-desktop.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
diff --git a/examples/declarative/accessibility/widgets/Checkbox.qml b/examples/quick/accessibility/content/Checkbox.qml
index 17eb733197..17eb733197 100644
--- a/examples/declarative/accessibility/widgets/Checkbox.qml
+++ b/examples/quick/accessibility/content/Checkbox.qml
diff --git a/examples/declarative/accessibility/widgets/Slider.qml b/examples/quick/accessibility/content/Slider.qml
index 32aa6a3a41..32aa6a3a41 100644
--- a/examples/declarative/accessibility/widgets/Slider.qml
+++ b/examples/quick/accessibility/content/Slider.qml
diff --git a/examples/quick/keyinteraction/keyinteraction.pro b/examples/quick/keyinteraction/keyinteraction.pro
new file mode 100644
index 0000000000..890d5b1449
--- /dev/null
+++ b/examples/quick/keyinteraction/keyinteraction.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += quick declarative
+SOURCES += main.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/keyinteraction
+qml.files = keyinteraction.qml focus
+qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/keyinteraction
+INSTALLS += target qml
+
diff --git a/examples/quick/keyinteraction/keyinteraction.qml b/examples/quick/keyinteraction/keyinteraction.qml
new file mode 100644
index 0000000000..546ba4cf05
--- /dev/null
+++ b/examples/quick/keyinteraction/keyinteraction.qml
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) 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 "../../shared" as Examples
+
+/*!
+ \title QtQuick Examples - Key Interaction
+ \example quick/keyinteraction
+ \brief This is a collection of QML keyboard interaction examples.
+ \image qml-keyinteraction-example.png
+
+ This example demonstrates combining various methods of interacting with keyboard focus.
+*/
+
+Loader {//Just loader, since there's only one.
+ source: "focus/focus.qml"
+ focus: true
+ // Exception to the standard sizing, because this is primarily a desktop
+ // example and it benefits from being able to see everything at once.
+}
diff --git a/examples/quick/keyinteraction/keyinteraction.qmlproject b/examples/quick/keyinteraction/keyinteraction.qmlproject
new file mode 100644
index 0000000000..e8cbc449d5
--- /dev/null
+++ b/examples/quick/keyinteraction/keyinteraction.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "keyinteraction.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+}
diff --git a/examples/quick/keyinteraction/main.cpp b/examples/quick/keyinteraction/main.cpp
new file mode 100644
index 0000000000..1c9d67ef85
--- /dev/null
+++ b/examples/quick/keyinteraction/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) 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 "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(keyinteraction)
diff --git a/examples/quick/modelviews/listview/dynamiclist.qml b/examples/quick/modelviews/listview/dynamiclist.qml
index ee7c6329bc..e6d43a0d61 100644
--- a/examples/quick/modelviews/listview/dynamiclist.qml
+++ b/examples/quick/modelviews/listview/dynamiclist.qml
@@ -87,70 +87,84 @@ Rectangle {
Item {
id: delegateItem
- width: listView.width; height: 55
+ width: listView.width; height: 100
clip: true
- Row {
- anchors.verticalCenter: parent.verticalCenter
- spacing: 10
-
- Column {
- Image {
- source: "content/pics/arrow-up.png"
- MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index-1, 1) }
- }
- Image { source: "content/pics/arrow-down.png"
- MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index+1, 1) }
- }
+ Column {
+ id: arrows
+ anchors {
+ left: parent.left
+ verticalCenter: parent.verticalCenter
}
-
- Column {
- anchors.verticalCenter: parent.verticalCenter
-
- Text {
- text: name
- font.pixelSize: 15
- color: "white"
- }
- Row {
- spacing: 5
- Repeater {
- model: attributes
- Text { text: description; color: "White" }
- }
- }
+ Image {
+ source: "content/pics/arrow-up.png"
+ MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index-1, 1) }
+ }
+ Image { source: "content/pics/arrow-down.png"
+ MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index+1, 1) }
}
}
- Row {
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- spacing: 10
-
- PressAndHoldButton {
- anchors.verticalCenter: parent.verticalCenter
- source: "content/pics/plus-sign.png"
- onClicked: fruitModel.setProperty(index, "cost", cost + 0.25)
+ Column {
+ anchors {
+ left: arrows.right
+ horizontalCenter: parent.horizontalCenter;
+ bottom: parent.verticalCenter
}
- Text {
- id: costText
- anchors.verticalCenter: parent.verticalCenter
- text: '$' + Number(cost).toFixed(2)
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: name
font.pixelSize: 15
color: "white"
- font.bold: true
}
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 5
+ Repeater {
+ model: attributes
+ Text { text: description; color: "White" }
+ }
+ }
+ }
- PressAndHoldButton {
- anchors.verticalCenter: parent.verticalCenter
- source: "content/pics/minus-sign.png"
- onClicked: fruitModel.setProperty(index, "cost", Math.max(0,cost-0.25))
+ Item {
+ anchors {
+ left: arrows.right
+ horizontalCenter: parent.horizontalCenter;
+ top: parent.verticalCenter
+ bottom: parent.bottom
}
- Image {
- source: "content/pics/list-delete.png"
- MouseArea { anchors.fill:parent; onClicked: fruitModel.remove(index) }
+ Row {
+ anchors.centerIn: parent
+ spacing: 10
+
+ PressAndHoldButton {
+ anchors.verticalCenter: parent.verticalCenter
+ source: "content/pics/plus-sign.png"
+ onClicked: fruitModel.setProperty(index, "cost", cost + 0.25)
+ }
+
+ Text {
+ id: costText
+ anchors.verticalCenter: parent.verticalCenter
+ text: '$' + Number(cost).toFixed(2)
+ font.pixelSize: 15
+ color: "white"
+ font.bold: true
+ }
+
+ PressAndHoldButton {
+ anchors.verticalCenter: parent.verticalCenter
+ source: "content/pics/minus-sign.png"
+ onClicked: fruitModel.setProperty(index, "cost", Math.max(0,cost-0.25))
+ }
+
+ Image {
+ source: "content/pics/list-delete.png"
+ MouseArea { anchors.fill:parent; onClicked: fruitModel.remove(index) }
+ }
}
}
@@ -174,12 +188,17 @@ Rectangle {
// The view:
ListView {
id: listView
- anchors.fill: parent; anchors.margins: 20
+ anchors {
+ left: parent.left; top: parent.top;
+ right: parent.right; bottom: buttons.top;
+ margins: 20
+ }
model: fruitModel
delegate: listDelegate
}
Row {
+ id: buttons
anchors { left: parent.left; bottom: parent.bottom; margins: 20 }
spacing: 10
diff --git a/examples/quick/modelviews/listview/highlight.qml b/examples/quick/modelviews/listview/highlight.qml
index d8f76080e6..2dca1f4b18 100644
--- a/examples/quick/modelviews/listview/highlight.qml
+++ b/examples/quick/modelviews/listview/highlight.qml
@@ -69,6 +69,10 @@ Rectangle {
transitions: Transition {
NumberAnimation { properties: "x"; duration: 200 }
}
+ MouseArea {
+ anchors.fill: parent
+ onClicked: wrapper.ListView.view.currentIndex = index
+ }
}
}
diff --git a/examples/quick/modelviews/listview/highlightranges.qml b/examples/quick/modelviews/listview/highlightranges.qml
index a536ddcbb2..1cf5c06f45 100644
--- a/examples/quick/modelviews/listview/highlightranges.qml
+++ b/examples/quick/modelviews/listview/highlightranges.qml
@@ -44,7 +44,27 @@ import "content"
Rectangle {
id: root
property int current: 0
- width: 600; height: 300
+ // Example index automation for convenience, disabled on click or tap
+ SequentialAnimation on current {
+ id: anim
+ loops: -1
+ NumberAnimation {
+ duration: 5000
+ to: aModel.count - 1
+ }
+ NumberAnimation {
+ duration: 5000
+ to: 0
+ }
+ }
+ MouseArea{
+ id: ma
+ z: 1
+ anchors.fill: parent
+ onClicked: {ma.enabled = false; anim.running = false;}
+ }
+
+ width: 320; height: 480
// This example shows the same model in three different ListView items,
// with different highlight ranges. The highlight ranges are set by the
@@ -72,9 +92,10 @@ Rectangle {
ListView {
id: list1
- width: 200; height: parent.height
- model: PetsModel {}
+ height: 160; width: parent.width
+ model: PetsModel {id: aModel}
delegate: petDelegate
+ orientation: ListView.Horizontal
highlight: Rectangle { color: "lightsteelblue" }
currentIndex: root.current
@@ -84,10 +105,11 @@ Rectangle {
ListView {
id: list2
- x: list1.width
- width: 200; height: parent.height
+ y: list1.height
+ height: 160; width: parent.width
model: PetsModel {}
delegate: petDelegate
+ orientation: ListView.Horizontal
highlight: Rectangle { color: "yellow" }
currentIndex: root.current
@@ -97,10 +119,11 @@ Rectangle {
ListView {
id: list3
- x: list1.width + list2.width
- width: 200; height: parent.height
+ y: list1.height + list2.height
+ height: 160; width: parent.width
model: PetsModel {}
delegate: petDelegate
+ orientation: ListView.Horizontal
highlight: Rectangle { color: "yellow" }
currentIndex: root.current
@@ -112,11 +135,20 @@ Rectangle {
// The delegate for each list
Component {
id: petDelegate
- Column {
- width: 200
- Text { text: 'Name: ' + name }
- Text { text: 'Type: ' + type }
- Text { text: 'Age: ' + age }
+ Item {
+ width: 160
+ height: column.height
+ Column {
+ id: column
+ Text { text: 'Name: ' + name }
+ Text { text: 'Type: ' + type }
+ Text { text: 'Age: ' + age }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: wrapper.ListView.view.currentIndex = index
+ }
}
}
}
diff --git a/examples/quick/modelviews/main.cpp b/examples/quick/modelviews/main.cpp
new file mode 100644
index 0000000000..77f0e59b34
--- /dev/null
+++ b/examples/quick/modelviews/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) 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 "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(modelviews)
diff --git a/examples/quick/modelviews/modelviews.pro b/examples/quick/modelviews/modelviews.pro
index 7748da0471..59c5e231a2 100644
--- a/examples/quick/modelviews/modelviews.pro
+++ b/examples/quick/modelviews/modelviews.pro
@@ -1,8 +1,18 @@
-TEMPLATE = subdirs
+TEMPLATE = app
-SUBDIRS += \
- abstractitemmodel \
- objectlistmodel \
- stringlistmodel
+QT += quick qml
+SOURCES += main.cpp
+target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/modelviews
+qml.files = \
+ modelviews.qml \
+ gridview \
+ listview \
+ package \
+ parallax \
+ pathview \
+ visualdatamodel \
+ visualitemmodel
+qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/modelviews
+INSTALLS += target qml
diff --git a/examples/quick/modelviews/modelviews.qml b/examples/quick/modelviews/modelviews.qml
index f11608bcc7..ce0880c057 100644
--- a/examples/quick/modelviews/modelviews.qml
+++ b/examples/quick/modelviews/modelviews.qml
@@ -39,26 +39,49 @@
****************************************************************************/
import QtQuick 2.0
-import "../../shared"
+import "../../shared" as Examples
+
+/*!
+ \title QtQuick Examples - ModelViews
+ \example quick/modelviews
+ \brief This is a collection of QML drag and drop examples
+ \image qml-modelviews-example.png
+
+ This is a collection of small QML examples relating to model and view functionality.
+
+ GridView and PathView demonstrate usage of these elements to display views.
+
+ Dynamic List demonstrates runtime modification of a ListModel.
+
+ Expanding Delegates demonstrates delegates that expand when activated.
+
+ Highlight demonstrates adding a custom highlight to a ListView.
+
+ Highlight Ranges shows the three different highlight range modes of ListView.
+
+ Sections demonstrates the various section headers and footers available to ListView.
+
+ Packages demonstrates using Packages to transition delegates between two views.
+
+ VisualItemModel uses a VisualItemModel for the model instead of a ListModel.
+*/
Item {
height: 480
- width: 480
- LauncherList {
+ width: 320
+ Examples.LauncherList {
id: ll
anchors.fill: parent
Component.onCompleted: {
- addExample("Dynamic List", "A ListView harboring dynamic data", Qt.resolvedUrl("listview/dynamiclist.qml"));
- addExample("Expanding Delegates", "Delegates that expand to fill the list when clicked", Qt.resolvedUrl("listview/expandingdelegates.qml"));
- addExample("Highlight", "Adding a highlight to the current item", Qt.resolvedUrl("listview/highlight.qml"));
- addExample("Sections", "A ListView with section headers", Qt.resolvedUrl("listview/sections.qml"));
- addExample("GridView", "A view laid out in a grid", Qt.resolvedUrl("gridview/gridview-example.qml"));
- addExample("PathView", "A view laid out along a path", Qt.resolvedUrl("pathview/pathview-example.qml"));
- addExample("Package", "Using a package to transition items between views", Qt.resolvedUrl("package/view.qml"));
- addExample("Parallax", "Adds a background and a parallax effect to a ListView", Qt.resolvedUrl("parallax/parallax.qml"));
- addExample("Slideshow", "A model demonstrating delayed image loading", Qt.resolvedUrl("visualdatamodel/slideshow.qml"));
- addExample("Sorted Model", "Two views on a model, one of which is sorted", Qt.resolvedUrl("visualdatamodel/sortedmodel.qml"));
- addExample("VisualItemModel", "A model that consists of the actual Items", Qt.resolvedUrl("visualitemmodel/visualitemmodel.qml"));
+ addExample("GridView", "A simple GridView", Qt.resolvedUrl("gridview/gridview-example.qml"))
+ addExample("Dynamic List", "A dynamically alterable list", Qt.resolvedUrl("listview/dynamiclist.qml"))
+ addExample("Expanding Delegates", "A ListView with delegates that expand", Qt.resolvedUrl("listview/expandingdelegates.qml"))
+ addExample("Highlight", "A ListView with a custom highlight", Qt.resolvedUrl("listview/highlight.qml"))
+ addExample("Highlight Ranges", "The three highlight ranges of ListView", Qt.resolvedUrl("listview/highlightranges.qml"))
+ addExample("Sections", "ListView section headers and footers", Qt.resolvedUrl("listview/sections.qml"))
+ addExample("Packages", "Transitions between a ListView and GridView", Qt.resolvedUrl("package/view.qml"))
+ addExample("PathView", "A simple PathView", Qt.resolvedUrl("pathview/pathview-example.qml"))
+ addExample("VisualItemModel", "Using a VisualItemModel", Qt.resolvedUrl("visualitemmodel/visualitemmodel.qml"))
}
}
}
diff --git a/examples/quick/modelviews/package/Delegate.qml b/examples/quick/modelviews/package/Delegate.qml
index 97c7840cb4..3028318f10 100644
--- a/examples/quick/modelviews/package/Delegate.qml
+++ b/examples/quick/modelviews/package/Delegate.qml
@@ -42,26 +42,16 @@ import QtQuick 2.0
//![0]
Package {
- Text { id: listDelegate; width: 200; height: 25; text: 'Empty'; Package.name: 'list' }
- Text { id: gridDelegate; width: 100; height: 50; text: 'Empty'; Package.name: 'grid' }
+ Text { id: listDelegate; width: parent.width; height: 25; text: 'Empty'; Package.name: 'list' }
+ Text { id: gridDelegate; width: parent.width / 2; height: 50; text: 'Empty'; Package.name: 'grid' }
Rectangle {
id: wrapper
- width: 200; height: 25
+ width: parent.width; height: 25
color: 'lightsteelblue'
Text { text: display; anchors.centerIn: parent }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- if (wrapper.state == 'inList')
- wrapper.state = 'inGrid';
- else
- wrapper.state = 'inList';
- }
- }
-
- state: 'inList'
+ state: root.upTo > index ? 'inGrid' : 'inList'
states: [
State {
name: 'inList'
diff --git a/examples/quick/modelviews/package/view.qml b/examples/quick/modelviews/package/view.qml
index 7ba6664ae2..b12dec3de2 100644
--- a/examples/quick/modelviews/package/view.qml
+++ b/examples/quick/modelviews/package/view.qml
@@ -41,9 +41,16 @@
import QtQuick 2.0
Rectangle {
+ id: root
color: "white"
- width: 400
- height: 200
+ width: 320
+ height: 480
+ property int upTo: 0
+ SequentialAnimation on upTo {
+ loops: -1
+ NumberAnimation { to: 8; duration: 3500 }
+ NumberAnimation { to: 0; duration: 3500 }
+ }
ListModel {
id: myModel
@@ -64,17 +71,22 @@ Rectangle {
}
ListView {
- width: 200; height:200
+ id: lv
+ height: parent.height/2
+ width: parent.width
+
model: visualModel.parts.list
}
GridView {
- x: 200; width: 200; height:200
+ y: parent.height/2
+ height: parent.height/2
+ width: parent.width
+ cellWidth: width / 2
cellHeight: 50
model: visualModel.parts.grid
}
//![0]
Text {
anchors.bottom: parent.bottom
- text: "Tap a delegate to move between views"
}
}
diff --git a/examples/quick/modelviews/parallax/parallax.qml b/examples/quick/modelviews/parallax/parallax.qml
index 30578e510e..9e0a957f97 100644
--- a/examples/quick/modelviews/parallax/parallax.qml
+++ b/examples/quick/modelviews/parallax/parallax.qml
@@ -69,7 +69,7 @@ Rectangle {
anchors { top: parent.top; topMargin: 10; horizontalCenter: parent.horizontalCenter }
width: 300; height: 400
clip: true;
- source: "../../samegame/samegame.qml"
+ source: "../../../demos/samegame/samegame.qml"
}
}
}
diff --git a/examples/quick/modelviews/visualdatamodel/sortedmodel.qml b/examples/quick/modelviews/visualdatamodel/sortedmodel.qml
deleted file mode 100644
index 8d3b0a58e5..0000000000
--- a/examples/quick/modelviews/visualdatamodel/sortedmodel.qml
+++ /dev/null
@@ -1,141 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) nor
-** the names of its contributors may be used to endorse or promote
-** products derived from this software without specific prior written
-** permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Rectangle {
- width: 480; height: 640
-
- Component {
- id: numberDelegate
-
- Text {
- id: numberText
- anchors { left: parent.left; right: parent.right }
- text: number
-
- horizontalAlignment: Text.AlignHCenter
- font.pixelSize: 18
-
- Text {
- anchors { left: parent.left; baseline: parent.baseline }
- text: index
-
- horizontalAlignment: Text.AlignLeft
- font.pixelSize: 12
- }
- Text {
- anchors { right: parent.right; baseline: parent.baseline }
- text: numberText.VisualDataModel.itemsIndex
-
- horizontalAlignment: Text.AlignRight
- font.pixelSize: 12
- }
- }
- }
-
- ListView {
- anchors {
- left: parent.left; top: parent.top;
- right: parent.horizontalCenter; bottom: button.top
- leftMargin: 2; topMargin: 2; rightMargin: 1; bottomMargin: 2
- }
-
- model: ListModel {
- id: unsortedModel
- }
- delegate: numberDelegate
- }
- ListView {
- anchors {
- left: parent.horizontalCenter; top: parent.top;
- right: parent.right; bottom: button.top
- leftMargin: 1; topMargin: 2; rightMargin: 2; bottomMargin: 2
- }
- model: VisualDataModel {
- model: unsortedModel
- delegate: numberDelegate
-
- items.onChanged: {
- for (var i = 0; i < inserted.length; ++i) {
- for (var j = inserted[i].index; j < inserted[i].index + inserted[i].count; ++j) {
- var number = items.get(j).model.number
- for (var l = 0, k = 0; l < unsortedModel.count; ++l) {
- if (l == inserted[k].index) {
- l += inserted[k].count - 1
- ++k
- } else if (number < items.get(l).model.number) {
- items.move(j, l, 1)
- break
- }
- }
- inserted[i].index += 1;
- inserted[i].count -= 1;
- }
- }
- }
- }
- }
-
- Rectangle {
- id: button
-
- anchors { left: parent.left; right: parent.right; bottom: parent.bottom; margins: 2 }
- height: moreText.implicitHeight + 4
-
- color: "black"
-
- Text {
- id: moreText
-
- anchors.fill: parent
- text: "More"
- color: "white"
- font.pixelSize: 18
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- }
- MouseArea {
- anchors.fill: parent
-
- onClicked: unsortedModel.append({ "number": Math.floor(Math.random() * 100) })
- }
- }
-}
diff --git a/examples/quick/mousearea/main.cpp b/examples/quick/mousearea/main.cpp
new file mode 100644
index 0000000000..a85bac3b05
--- /dev/null
+++ b/examples/quick/mousearea/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) 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 "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(mousearea)
diff --git a/examples/quick/mousearea/mousearea.pro b/examples/quick/mousearea/mousearea.pro
new file mode 100644
index 0000000000..e9a715aae5
--- /dev/null
+++ b/examples/quick/mousearea/mousearea.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += quick declarative
+SOURCES += main.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/mousearea
+qml.files = mousearea.qml
+qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/mousearea
+INSTALLS += target qml
+
diff --git a/examples/quick/mousearea/mousearea-example.qml b/examples/quick/mousearea/mousearea.qml
index 30e3e62864..df26e05a3c 100644
--- a/examples/quick/mousearea/mousearea-example.qml
+++ b/examples/quick/mousearea/mousearea.qml
@@ -40,9 +40,18 @@
import QtQuick 2.0
+/*!
+ \title QtQuick Examples - MouseArea
+ \example quick/mousearea
+ \brief This is a collection of QML Animation examples.
+ \image qml-mousearea-example.png
+
+ This example shows you how to respond to clicks and drags with a MouseArea.
+*/
+
Rectangle {
id: box
- width: 400; height: 300
+ width: 320; height: 480
Rectangle {
id: redSquare
diff --git a/examples/quick/mousearea/mousearea.qmlproject b/examples/quick/mousearea/mousearea.qmlproject
new file mode 100644
index 0000000000..6595e118d8
--- /dev/null
+++ b/examples/quick/mousearea/mousearea.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "mousearea.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+}
diff --git a/examples/quick/openglunderqml/main.cpp b/examples/quick/openglunderqml/main.cpp
index 3b682deaec..8d1a91bdb2 100644
--- a/examples/quick/openglunderqml/main.cpp
+++ b/examples/quick/openglunderqml/main.cpp
@@ -49,7 +49,7 @@ int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
- qmlRegisterType<Squircle>("QtQuick", 2, 0, "Squircle");
+ qmlRegisterType<Squircle>("OpenGLUnderQML", 2, 0, "Squircle");
QQuickView view;
view.setSource(QUrl("main.qml"));
diff --git a/examples/quick/openglunderqml/main.qml b/examples/quick/openglunderqml/main.qml
index 1485cbbdb8..174bb262ca 100644
--- a/examples/quick/openglunderqml/main.qml
+++ b/examples/quick/openglunderqml/main.qml
@@ -40,13 +40,16 @@
****************************************************************************/
import QtQuick 2.0
+import OpenGLUnderQML 2.0
Item {
- width: 400
- height: 300
+ width: 320
+ height: 480
Squircle {
+ width: 320
+ height: 320
SequentialAnimation on t {
NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
diff --git a/examples/quick/painteditem/smile/smile.qml b/examples/quick/painteditem/smile/smile.qml
index 33919bc04f..c30da1b944 100644
--- a/examples/quick/painteditem/smile/smile.qml
+++ b/examples/quick/painteditem/smile/smile.qml
@@ -40,93 +40,41 @@
import QtQuick 2.0
import MyModule 1.0
+/*!
+ \title QtQuick Examples - Painted Smile
+ \example quick/painteditem/smile
+ \brief This is a simple example the draws a smile with QPainter
+*/
Rectangle {
- width: 500
- height: 500
+ width: 320
+ height: 480
gradient: Gradient {
GradientStop { position: 0.0; color: "#00249a" }
GradientStop { position: 0.7; color: "#ffd94f" }
GradientStop { position: 1.0; color: "#ffa322" }
}
- MyPaintItem {
- renderTarget:PaintedItem.Image
- clip:true
- width:240
- height:240
- anchors.left : parent.left
- anchors.top :parent.top
- anchors.margins: 10
- smooth: true
- MouseArea {
- anchors.fill:parent
- onClicked: {
- if (parent.face == ":-)")
- parent.face = ":-(";
- else
- parent.face = ":-)";
- parent.update()
- }
+ Grid {
+ columns: 2
+ Repeater {
+ model: 6
+ delegate: MyPaintItem {
+ renderTarget:PaintedItem.Image
+ clip:true
+ width:160
+ height:160
+ smooth: true
+ MouseArea {
+ anchors.fill:parent
+ onClicked: {
+ if (parent.face == ":-)")
+ parent.face = ":-(";
+ else
+ parent.face = ":-)";
+ parent.update()
+ }
+ }
+ }
}
}
- MyPaintItem {
- clip:true
- renderTarget:PaintedItem.Image
- width:240
- height:240
- anchors.right : parent.right
- anchors.top :parent.top
- anchors.margins: 10
- smooth: true
- MouseArea {
- anchors.fill:parent
- onClicked: {
- if (parent.face == ":-)")
- parent.face = ":-(";
- else
- parent.face = ":-)";
- parent.update()
- }
- }
- }
- MyPaintItem {
- clip:true
- renderTarget:PaintedItem.Image
- width:240
- height:240
- anchors.left : parent.left
- anchors.bottom :parent.bottom
- anchors.margins: 10
- smooth: true
- MouseArea {
- anchors.fill:parent
- onClicked: {
- if (parent.face == ":-)")
- parent.face = ":-(";
- else
- parent.face = ":-)";
- parent.update()
- }
- }
- }
- MyPaintItem {
- clip:true
- renderTarget:PaintedItem.Image
- width:240
- height:240
- anchors.right : parent.right
- anchors.bottom :parent.bottom
- anchors.margins: 10
- smooth: true
- MouseArea {
- anchors.fill:parent
- onClicked: {
- if (parent.face == ":-)")
- parent.face = ":-(";
- else
- parent.face = ":-)";
- parent.update()
- }
- }
- }
-} \ No newline at end of file
+}
diff --git a/examples/quick/painteditem/textballoons/textballoons.qml b/examples/quick/painteditem/textballoons/textballoons.qml
index b00ce2bfed..d5151c9553 100644
--- a/examples/quick/painteditem/textballoons/textballoons.qml
+++ b/examples/quick/painteditem/textballoons/textballoons.qml
@@ -42,9 +42,14 @@
import QtQuick 2.0
import TextBalloonPlugin 1.0
+/*!
+ \title QtQuick Examples - Painted Text Balloons
+ \example quick/painteditem/textballoons
+ \brief This is a simple example that draws text balloons using QPainter
+*/
Item {
height: 480
- width: 640
+ width: 320
//! [0]
ListModel {
@@ -53,7 +58,7 @@ Item {
balloonWidth: 200
}
ListElement {
- balloonWidth: 350
+ balloonWidth: 120
}
}
@@ -95,7 +100,7 @@ Item {
anchors.fill: parent
hoverEnabled: true
onClicked: {
- balloonModel.append({"balloonWidth": Math.floor(Math.random() * 300 + 100)})
+ balloonModel.append({"balloonWidth": Math.floor(Math.random() * 200 + 100)})
balloonView.positionViewAtIndex(balloonView.count -1, ListView.End)
}
onEntered: {
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index 529f65ac25..d715d4787c 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -1,11 +1,11 @@
TEMPLATE = subdirs
SUBDIRS = accessibility \
animation \
- draganddrop
+ draganddrop \
#canvas \
#imageelements \
#keyinteraction \
- #modelviews \
+ modelviews \
#mousearea \
#openglunderqml \
#painteditem \
diff --git a/examples/quick/threading/main.cpp b/examples/quick/threading/main.cpp
new file mode 100644
index 0000000000..e3440b1e4c
--- /dev/null
+++ b/examples/quick/threading/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) 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 "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(threading)
diff --git a/examples/quick/threading/threading.pro b/examples/quick/threading/threading.pro
new file mode 100644
index 0000000000..ba6d75433b
--- /dev/null
+++ b/examples/quick/threading/threading.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += quick qml
+SOURCES += main.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/threading
+qml.files = threading.qml threadedlistmodel workerscript
+qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/threading
+INSTALLS += target qml
+
diff --git a/examples/quick/threading/threading.qml b/examples/quick/threading/threading.qml
new file mode 100644
index 0000000000..7ba8b8f70d
--- /dev/null
+++ b/examples/quick/threading/threading.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) 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 "../../shared" as Examples
+
+/*!
+ \title QtQuick Examples - Threading
+ \example qtquick/threading
+ \brief This is a collection of QML Multithreading examples.
+ \image qml-threading-example.png
+
+ Threaded ListModel contains a ListView and a ListModel. The ListModel is updated asynchronusly in another thread, and the results propagate back to the main thread.
+
+ WorkerScript contains an example of using a WorkerScript to offload expensive calculations into another thread. This keeps the UI from being blocked. This example calculates numbers in Pascal's Triangle, and not in a very optimal way, so it will often take several seconds to complete the calculation. By doing this in a WorkerScript in another thread, the UI is not blocked during this time.
+*/
+
+Item {
+ height: 480
+ width: 320
+ Examples.LauncherList {
+ id: ll
+ anchors.fill: parent
+ Component.onCompleted: {
+ addExample("Threaded ListModel", "Updates a ListModel in another thread", Qt.resolvedUrl("threadedlistmodel/timedisplay.qml"));
+ addExample("WorkerScript", "Performs calculations in another thread", Qt.resolvedUrl("workerscript/workerscript.qml"));
+ }
+ }
+}
diff --git a/examples/quick/threading/threading.qmlproject b/examples/quick/threading/threading.qmlproject
new file mode 100644
index 0000000000..d17405d4dc
--- /dev/null
+++ b/examples/quick/threading/threading.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "threading.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+}
diff --git a/examples/quick/threading/workerscript/Spinner.qml b/examples/quick/threading/workerscript/Spinner.qml
new file mode 100644
index 0000000000..32ab248529
--- /dev/null
+++ b/examples/quick/threading/workerscript/Spinner.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 64
+ height: 64
+ property alias value: list.currentIndex
+ property alias label: caption.text
+
+ Text {
+ id: caption
+ text: "Spinner"
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ Rectangle {
+ anchors.top: caption.bottom
+ anchors.topMargin: 4
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: 48
+ width: 32
+ color: "black"
+ ListView {
+ id: list
+ anchors.fill: parent
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ preferredHighlightBegin: height/3
+ preferredHighlightEnd: height/3
+ clip: true
+ model: 64
+ delegate: Text {
+ font.pixelSize: 18;
+ color: "white";
+ text: index;
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+ Rectangle {
+ anchors.fill: parent
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#FF000000" }
+ GradientStop { position: 0.2; color: "#00000000" }
+ GradientStop { position: 0.8; color: "#00000000" }
+ GradientStop { position: 1.0; color: "#FF000000" }
+ }
+ }
+ }
+}
diff --git a/examples/quick/threading/workerscript/workerscript.js b/examples/quick/threading/workerscript/workerscript.js
index f76471f920..ada3d82589 100644
--- a/examples/quick/threading/workerscript/workerscript.js
+++ b/examples/quick/threading/workerscript/workerscript.js
@@ -1,15 +1,24 @@
-var lastx = 0;
-var lasty = 0;
+//Will be initialized when WorkerScript{} is instantiated
+var cache = new Array(64);
+for (var i = 0; i < 64; i++)
+ cache[i] = new Array(64);
-WorkerScript.onMessage = function(message) {
- var ydiff = message.y - lasty;
- var xdiff = message.x - lastx;
-
- var total = Math.sqrt(ydiff * ydiff + xdiff * xdiff);
-
- lastx = message.x;
- lasty = message.y;
+function triangle(row, column) {
+ if (cache[row][column])
+ return cache[row][column]
+ if (column < 0 || column > row)
+ return -1;
+ if (column == 0 || column == row)
+ return 1;
+ return triangle(row-1, column-1) + triangle(row-1, column);
+}
- WorkerScript.sendMessage( {xmove: xdiff, ymove: ydiff, move: total} );
+WorkerScript.onMessage = function(message) {
+ //Calculate result (may take a while, using a naive algorithm)
+ var calculatedResult = triangle(message.row, message.column);
+ //Send result back to main thread
+ WorkerScript.sendMessage( { row: message.row,
+ column: message.column,
+ result: calculatedResult} );
}
diff --git a/examples/quick/threading/workerscript/workerscript.qml b/examples/quick/threading/workerscript/workerscript.qml
index 7fced8166c..640df0b483 100644
--- a/examples/quick/threading/workerscript/workerscript.qml
+++ b/examples/quick/threading/workerscript/workerscript.qml
@@ -41,43 +41,55 @@
import QtQuick 2.0
Rectangle {
- width: 480; height: 320
+ width: 320; height: 480
WorkerScript {
id: myWorker
source: "workerscript.js"
onMessage: {
- console.log("Moved " + messageObject.xmove + " along the X axis.");
- console.log("Moved " + messageObject.ymove + " along the Y axis.");
- console.log("Moved " + messageObject.move + " pixels.");
+ if (messageObject.row == rowSpinner.value && messageObject.column == columnSpinner.value){ //Not an old result
+ if (messageObject.result == -1)
+ resultText.text = "Column must be <= Row";
+ else
+ resultText.text = messageObject.result;
+ }
}
}
+ Row {
+ y: 24
+ spacing: 24
+ anchors.horizontalCenter: parent.horizontalCenter
+ Spinner {
+ id: rowSpinner
+ label: "Row"
+ onValueChanged: {
+ resultText.text = "Loading...";
+ myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
+ }
+ }
- Rectangle {
- width: 200; height: 200
- anchors.left: parent.left; anchors.leftMargin: 20
- color: "red"
-
- MouseArea {
- anchors.fill: parent
- onClicked: myWorker.sendMessage( { rectangle: "red", x: mouse.x, y: mouse.y } );
+ Spinner {
+ id: columnSpinner
+ label: "Column"
+ onValueChanged: {
+ resultText.text = "Loading...";
+ myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
+ }
}
}
- Rectangle {
- width: 200; height: 200
- anchors.right: parent.right; anchors.rightMargin: 20
- color: "blue"
-
- MouseArea {
- anchors.fill: parent
- onClicked: myWorker.sendMessage( { rectangle: "blue", x: mouse.x, y: mouse.y } );
- }
+ Text {
+ id: resultText
+ y: 180
+ width: parent.width
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.WordWrap
+ font.pixelSize: 32
}
Text {
- text: "Click a Rectangle!"
+ text: "Pascal's Triangle Calculator"
anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 50 }
}
}
diff --git a/examples/quick/touchinteraction/flickable/basic-flickable.qml b/examples/quick/touchinteraction/flickable/basic-flickable.qml
new file mode 100644
index 0000000000..58650d7334
--- /dev/null
+++ b/examples/quick/touchinteraction/flickable/basic-flickable.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 320
+ height: 480
+ Flickable {
+ anchors.fill: parent
+ contentWidth: 1200
+ contentHeight: 1200
+ Rectangle {
+ width: 1000
+ height: 1000
+ x: 100
+ y: 100
+ radius: 128
+ border.width: 4
+ border.color: "black"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#000000" }
+ GradientStop { position: 0.2; color: "#888888" }
+ GradientStop { position: 0.4; color: "#FFFFFF" }
+ GradientStop { position: 0.6; color: "#FFFFFF" }
+ GradientStop { position: 0.8; color: "#888888" }
+ GradientStop { position: 1.0; color: "#000000" }
+ }
+ }
+ }
+}
diff --git a/examples/quick/touchinteraction/flickable/content/Day.qml b/examples/quick/touchinteraction/flickable/content/Panel.qml
index 7fe625c305..3a402bbc06 100644
--- a/examples/quick/touchinteraction/flickable/content/Day.qml
+++ b/examples/quick/touchinteraction/flickable/content/Panel.qml
@@ -48,7 +48,7 @@ Component {
width: ListView.view.width+40; height: ListView.view.height
- Image {
+ Image {
source: "cork.jpg"
width: page.ListView.view.width
height: page.ListView.view.height
diff --git a/examples/quick/touchinteraction/flickable/corkboards.qml b/examples/quick/touchinteraction/flickable/corkboards.qml
index dc3aa6b378..85c62f1538 100644
--- a/examples/quick/touchinteraction/flickable/corkboards.qml
+++ b/examples/quick/touchinteraction/flickable/corkboards.qml
@@ -42,62 +42,33 @@ import QtQuick 2.0
import "content"
Rectangle {
- width: 800; height: 480
+ width: 320; height: 480
color: "#464646"
ListModel {
id: list
ListElement {
- name: "Sunday"
+ name: "Panel One"
notes: [
- ListElement { noteText: "Lunch" },
- ListElement { noteText: "Birthday Party" }
+ ListElement { noteText: "Tap to edit" },
+ ListElement { noteText: "Drag to move" },
+ ListElement { noteText: "Flick to scroll" }
]
}
ListElement {
- name: "Monday"
+ name: "Panel Two"
notes: [
- ListElement { noteText: "Pickup kids from\nschool\n4.30pm" },
- ListElement { noteText: "Checkout Qt" }, ListElement { noteText: "Read email" }
+ ListElement { noteText: "Note One" },
+ ListElement { noteText: "Note Two" }
]
}
ListElement {
- name: "Tuesday"
+ name: "Panel Three"
notes: [
- ListElement { noteText: "Walk dog" },
- ListElement { noteText: "Buy newspaper" }
- ]
- }
-
- ListElement {
- name: "Wednesday"
- notes: [ ListElement { noteText: "Cook dinner" } ]
- }
-
- ListElement {
- name: "Thursday"
- notes: [
- ListElement { noteText: "Meeting\n5.30pm" },
- ListElement { noteText: "Weed garden" }
- ]
- }
-
- ListElement {
- name: "Friday"
- notes: [
- ListElement { noteText: "More work" },
- ListElement { noteText: "Grocery shopping" }
- ]
- }
-
- ListElement {
- name: "Saturday"
- notes: [
- ListElement { noteText: "Drink" },
- ListElement { noteText: "Download Qt\nPlay with QML" }
+ ListElement { noteText: "Note Three" }
]
}
}
@@ -111,6 +82,6 @@ Rectangle {
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
model: list
- delegate: Day { }
+ delegate: Panel { }
}
}
diff --git a/examples/quick/touchinteraction/main.cpp b/examples/quick/touchinteraction/main.cpp
new file mode 100644
index 0000000000..02b249dace
--- /dev/null
+++ b/examples/quick/touchinteraction/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples 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 Nokia Corporation and its Subsidiary(-ies) 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 "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(touchinteraction)
diff --git a/examples/quick/touchinteraction/multipointtouch/bearwhack.qml b/examples/quick/touchinteraction/multipointtouch/bearwhack.qml
index db46473c05..e2910a3c5d 100644
--- a/examples/quick/touchinteraction/multipointtouch/bearwhack.qml
+++ b/examples/quick/touchinteraction/multipointtouch/bearwhack.qml
@@ -43,7 +43,7 @@ import "content"
Item {
id: root
- height: 640
+ height: 480
width: 320
Item {
id: startScreen
diff --git a/examples/quick/touchinteraction/multipointtouch/content/title.png b/examples/quick/touchinteraction/multipointtouch/content/title.png
index d630ea2643..c370ee9990 100644
--- a/examples/quick/touchinteraction/multipointtouch/content/title.png
+++ b/examples/quick/touchinteraction/multipointtouch/content/title.png
Binary files differ
diff --git a/examples/quick/touchinteraction/touchinteraction.pro b/examples/quick/touchinteraction/touchinteraction.pro
new file mode 100644
index 0000000000..c56e5c8206
--- /dev/null
+++ b/examples/quick/touchinteraction/touchinteraction.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += quick declarative
+SOURCES += main.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/touchinteraction
+qml.files = flickable multipointtouch pincharea touchinteraction.qml
+qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/quick/touchinteraction
+INSTALLS += target qml
+
diff --git a/examples/quick/touchinteraction/touchinteraction.qml b/examples/quick/touchinteraction/touchinteraction.qml
index b4a930c495..0be625a160 100644
--- a/examples/quick/touchinteraction/touchinteraction.qml
+++ b/examples/quick/touchinteraction/touchinteraction.qml
@@ -41,6 +41,25 @@
import QtQuick 2.0
import "../../shared"
+/*!
+ \title QtQuick Examples - Touch Interaction
+ \example qtquick/touchinteraction
+ \brief This is a collection of QML Touch Interaction examples.
+ \image qml-touchinteraction-example.png
+
+ This is a collection of small QML examples relating to touch interaction methods.
+
+ Multipoint Flames demonstrates distinguishing different fingers in a MultiPointTouchArea, by assignning a different colored flame to each touch point.
+
+ Bear-Whack demonstrates using a MultiPointTouchArea to add multiple finger support to a simple game.
+
+ Flick Resize uses a PinchArea to allow Pinch-to-Resize behavior.
+
+ Flickable is a simple example demonstrating the Flickable element.
+
+ Corkboards shows a more complex Flickable usecase, with elements on the flickable that respond to mouse and keyboard interaction.
+*/
+
Item {
height: 480
width: 320
@@ -51,6 +70,8 @@ Item {
addExample("Multipoint Flames", "Create multiple flames with multiple fingers", Qt.resolvedUrl("multipointtouch/multiflame.qml"));
addExample("Bear-Whack", "Use multiple touches to knock all the bears down", Qt.resolvedUrl("multipointtouch/bearwhack.qml"));
addExample("Flick Resize", "Manipulate images using pinch gestures", Qt.resolvedUrl("pincharea/flickresize.qml"));
+ addExample("Flickable", "A viewport you can move with touch gestures", Qt.resolvedUrl("flickable/basic-flickable.qml"));
+ addExample("Corkboards", "Uses touch input on items inside a Flickable", Qt.resolvedUrl("flickable/corkboards.qml"));
}
}
}
diff --git a/examples/tutorials/helloworld/tutorial1.qml b/examples/tutorials/helloworld/tutorial1.qml
index f0eb42d696..3de79831f4 100644
--- a/examples/tutorials/helloworld/tutorial1.qml
+++ b/examples/tutorials/helloworld/tutorial1.qml
@@ -46,7 +46,7 @@ import QtQuick 2.0
//![1]
Rectangle {
id: page
- width: 500; height: 200
+ width: 320; height: 480
color: "lightgray"
//![1]
diff --git a/examples/tutorials/helloworld/tutorial2.qml b/examples/tutorials/helloworld/tutorial2.qml
index c5c045aace..3b44f5cf54 100644
--- a/examples/tutorials/helloworld/tutorial2.qml
+++ b/examples/tutorials/helloworld/tutorial2.qml
@@ -43,7 +43,7 @@ import QtQuick 2.0
Rectangle {
id: page
- width: 500; height: 200
+ width: 320; height: 480
color: "lightgray"
Text {
diff --git a/examples/tutorials/helloworld/tutorial3.qml b/examples/tutorials/helloworld/tutorial3.qml
index c804bfca1d..c35420c1de 100644
--- a/examples/tutorials/helloworld/tutorial3.qml
+++ b/examples/tutorials/helloworld/tutorial3.qml
@@ -43,7 +43,7 @@ import QtQuick 2.0
Rectangle {
id: page
- width: 500; height: 200
+ width: 320; height: 480
color: "lightgray"
Text {
diff --git a/src/3rdparty/javascriptcore/DateMath.cpp b/src/3rdparty/javascriptcore/DateMath.cpp
index 9f66d91013..be99d2ca25 100644
--- a/src/3rdparty/javascriptcore/DateMath.cpp
+++ b/src/3rdparty/javascriptcore/DateMath.cpp
@@ -345,8 +345,15 @@ double timeClip(double t)
return NaN;
return t >= 0 ? floor(t) : ceil(t);
#else
+
+#if defined(__QNXNTO__)
+ if (!isfinite(t) || fabs(t) > maxECMAScriptTime)
+ return NaN;
+#else
if (!std::isfinite(t) || fabs(t) > maxECMAScriptTime)
return NaN;
+#endif
+
return trunc(t);
#endif
}
diff --git a/src/imports/folderlistmodel/folderlistmodel.pro b/src/imports/folderlistmodel/folderlistmodel.pro
index 592d8375c8..f30c2b2097 100644
--- a/src/imports/folderlistmodel/folderlistmodel.pro
+++ b/src/imports/folderlistmodel/folderlistmodel.pro
@@ -2,7 +2,7 @@ TARGET = qmlfolderlistmodelplugin
TARGETPATH = Qt/labs/folderlistmodel
include(../qimportbase.pri)
-QT += qml
+QT += core-private qml qml-private v8-private
SOURCES += qquickfolderlistmodel.cpp plugin.cpp \
fileinfothread.cpp
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 294fe184d2..0aabb7ae74 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -43,8 +43,8 @@
#include "qquickfolderlistmodel.h"
#include "fileinfothread_p.h"
#include "fileproperty_p.h"
-#include <QDebug>
#include <qqmlcontext.h>
+#include <private/qqmlengine_p.h>
QT_BEGIN_NAMESPACE
@@ -365,7 +365,8 @@ void QQuickFolderListModel::setFolder(const QUrl &folder)
if (folder == d->currentDir)
return;
- QString resolvedPath = QDir::cleanPath(folder.path());
+ QString localPath = QQmlEnginePrivate::urlToLocalFileOrQrc(folder);
+ QString resolvedPath = QDir::cleanPath(QUrl(localPath).path());
beginResetModel();
@@ -407,7 +408,8 @@ void QQuickFolderListModel::setRootFolder(const QUrl &path)
if (path.isEmpty())
return;
- QString resolvedPath = QDir::cleanPath(path.path());
+ QString localPath = QQmlEnginePrivate::urlToLocalFileOrQrc(path);
+ QString resolvedPath = QDir::cleanPath(QUrl(localPath).path());
QFileInfo info(resolvedPath);
if (!info.exists() || !info.isDir())
diff --git a/src/plugins/accessible/shared/qqmlaccessible.cpp b/src/plugins/accessible/shared/qqmlaccessible.cpp
index 70c6b90efe..54d0c06171 100644
--- a/src/plugins/accessible/shared/qqmlaccessible.cpp
+++ b/src/plugins/accessible/shared/qqmlaccessible.cpp
@@ -158,9 +158,9 @@ void QQmlAccessible::doAction(const QString &actionName)
{
// Look for and call the accessible[actionName]Action() function on the item.
// This allows for overriding the default action handling.
- const QByteArray functionName = "accessible" + actionName.toLatin1() + "Action()";
- if (object()->metaObject()->indexOfMethod(functionName) != -1) {
- QMetaObject::invokeMethod(object(), functionName, Q_ARG(QString, actionName));
+ const QByteArray functionName = "accessible" + actionName.toLatin1() + "Action";
+ if (object()->metaObject()->indexOfMethod(functionName + "()") != -1) {
+ QMetaObject::invokeMethod(object(), functionName);
return;
}
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
index 7d120cacb0..4dfed6c673 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
@@ -115,10 +115,11 @@ bool QmlOstPlugin::waitForMessage()
return d->protocol->waitForReadyRead(-1);
}
-void QmlOstPlugin::setPort(int port, bool block)
+void QmlOstPlugin::setPort(int port, bool block, const QString &hostaddress)
{
Q_UNUSED(port);
Q_UNUSED(block);
+ Q_UNUSED(hostaddress);
Q_D(QmlOstPlugin);
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
index 41c3a07f25..257962570c 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
@@ -63,7 +63,7 @@ public:
~QmlOstPlugin();
void setServer(QQmlDebugServer *server);
- void setPort(int port, bool bock);
+ void setPort(int port, bool bock, const QString &hostaddress);
bool isConnected() const;
void send(const QByteArray &message);
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
index 0c5e196b18..fdd1f6e05f 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
+++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
@@ -9,10 +9,14 @@ DESTDIR = $$QT.qml.plugins/qmltooling
QTDIR_build:REQUIRES += "contains(QT_CONFIG, qml)"
SOURCES += \
- qtcpserverconnection.cpp
+ qtcpserverconnection.cpp \
+ ../shared/qpacketprotocol.cpp
HEADERS += \
- qtcpserverconnection.h
+ qtcpserverconnection.h \
+ ../shared/qpacketprotocol.h
+
+INCLUDEPATH += ../shared
OTHER_FILES += qtcpserverconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 4eccd0dd55..724155a8f5 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -40,13 +40,13 @@
****************************************************************************/
#include "qtcpserverconnection.h"
+#include "qpacketprotocol.h"
#include <QtCore/qplugin.h>
#include <QtNetwork/qtcpserver.h>
#include <QtNetwork/qtcpsocket.h>
#include <private/qqmldebugserver_p.h>
-#include <private/qpacketprotocol_p.h>
QT_BEGIN_NAMESPACE
@@ -56,6 +56,7 @@ public:
int port;
bool block;
+ QString hostaddress;
QTcpSocket *socket;
QPacketProtocol *protocol;
QTcpServer *tcpServer;
@@ -129,11 +130,12 @@ bool QTcpServerConnection::waitForMessage()
return d->protocol->waitForReadyRead(-1);
}
-void QTcpServerConnection::setPort(int port, bool block)
+void QTcpServerConnection::setPort(int port, bool block, const QString &hostaddress)
{
Q_D(QTcpServerConnection);
d->port = port;
d->block = block;
+ d->hostaddress = hostaddress;
listen();
if (block)
@@ -146,7 +148,17 @@ void QTcpServerConnection::listen()
d->tcpServer = new QTcpServer(this);
QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
- if (d->tcpServer->listen(QHostAddress::Any, d->port))
+ QHostAddress hostaddress;
+ if (!d->hostaddress.isEmpty()) {
+ if (!hostaddress.setAddress(d->hostaddress)) {
+ hostaddress = QHostAddress::Any;
+ qDebug("QML Debugger: Incorrect host address provided. So accepting connections "
+ "from any host.");
+ }
+ } else {
+ hostaddress = QHostAddress::Any;
+ }
+ if (d->tcpServer->listen(hostaddress, d->port))
qDebug("QML Debugger: Waiting for connection on port %d...", d->port);
else
qWarning("QML Debugger: Unable to listen to port %d.", d->port);
@@ -194,4 +206,3 @@ void QTcpServerConnection::invalidPacket()
}
QT_END_NAMESPACE
-
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
index e81c9f7f0f..e2b32b0e4a 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
@@ -62,7 +62,7 @@ public:
~QTcpServerConnection();
void setServer(QQmlDebugServer *server);
- void setPort(int port, bool bock);
+ void setPort(int port, bool bock, const QString &hostaddress);
bool isConnected() const;
void send(const QList<QByteArray> &messages);
diff --git a/src/qml/debugger/qpacketprotocol.cpp b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
index 978054a238..a6a4e0e886 100644
--- a/src/qml/debugger/qpacketprotocol.cpp
+++ b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include "qpacketprotocol_p.h"
+#include "qpacketprotocol.h"
#include <QtCore/QBuffer>
#include <QtCore/QElapsedTimer>
diff --git a/src/qml/debugger/qpacketprotocol_p.h b/src/plugins/qmltooling/shared/qpacketprotocol.h
index c6123d2836..0470c74643 100644
--- a/src/qml/debugger/qpacketprotocol_p.h
+++ b/src/plugins/qmltooling/shared/qpacketprotocol.h
@@ -42,34 +42,18 @@
#ifndef QPACKETPROTOCOL_H
#define QPACKETPROTOCOL_H
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
#include <QtCore/qobject.h>
#include <QtCore/qdatastream.h>
-#include <private/qtqmlglobal_p.h>
-
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
-
class QIODevice;
class QBuffer;
class QPacket;
class QPacketAutoSend;
class QPacketProtocolPrivate;
-class Q_QML_PRIVATE_EXPORT QPacketProtocol : public QObject
+class QPacketProtocol : public QObject
{
Q_OBJECT
public:
@@ -101,7 +85,7 @@ private:
};
-class Q_QML_PRIVATE_EXPORT QPacket : public QDataStream
+class QPacket : public QDataStream
{
public:
QPacket();
@@ -119,7 +103,7 @@ protected:
QBuffer *buf;
};
-class Q_QML_PRIVATE_EXPORT QPacketAutoSend : public QPacket
+class QPacketAutoSend : public QPacket
{
public:
virtual ~QPacketAutoSend();
@@ -132,6 +116,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index f5abd2c196..f16e225cfd 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -1,5 +1,4 @@
SOURCES += \
- $$PWD/qpacketprotocol.cpp \
$$PWD/qqmldebugservice.cpp \
$$PWD/qqmlprofilerservice.cpp \
$$PWD/qqmldebugserver.cpp \
@@ -10,7 +9,6 @@ SOURCES += \
$$PWD/qdebugmessageservice.cpp
HEADERS += \
- $$PWD/qpacketprotocol_p.h \
$$PWD/qqmldebugservice_p.h \
$$PWD/qqmldebugservice_p_p.h \
$$PWD/qqmlprofilerservice_p.h \
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
index ec3f9dafc2..dcf93b400e 100644
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ b/src/qml/debugger/qqmldebugserver.cpp
@@ -117,9 +117,10 @@ public:
m_pluginName = pluginName;
}
- void setPort(int port, bool block) {
+ void setPort(int port, bool block, QString &hostAddress) {
m_port = port;
m_block = block;
+ m_hostAddress = hostAddress;
}
void run();
@@ -128,6 +129,7 @@ private:
QString m_pluginName;
int m_port;
bool m_block;
+ QString m_hostAddress;
};
QQmlDebugServerPrivate::QQmlDebugServerPrivate() :
@@ -214,7 +216,7 @@ void QQmlDebugServerThread::run()
= server->d_func()->loadConnectionPlugin(m_pluginName);
if (connection) {
connection->setServer(QQmlDebugServer::instance());
- connection->setPort(m_port, m_block);
+ connection->setPort(m_port, m_block, m_hostAddress);
} else {
QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
qWarning() << QString(QLatin1String("QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
@@ -258,8 +260,9 @@ QQmlDebugServer *QQmlDebugServer::instance()
int port = 0;
bool block = false;
bool ok = false;
+ QString hostAddress;
- // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block]
+ // format: qmljsdebugger=port:3768[,host:<ip address>][,block] OR qmljsdebugger=ost[,block]
if (!appD->qmljsDebugArgumentsString().isEmpty()) {
if (!QQmlEnginePrivate::qml_debugging_enabled) {
qWarning() << QString(QLatin1String(
@@ -270,24 +273,30 @@ QQmlDebugServer *QQmlDebugServer::instance()
}
QString pluginName;
- if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) {
- int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(','));
- port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok);
- pluginName = QStringLiteral("qmldbg_tcp");
- } else if (appD->qmljsDebugArgumentsString().contains(QLatin1String("ost"))) {
- pluginName = QStringLiteral("qmldbg_ost");
- ok = true;
+ QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString()
+ .split(QLatin1Char(','));
+ foreach (const QString &strArgument, lstjsDebugArguments) {
+ if (strArgument.startsWith(QLatin1String("port:"))) {
+ port = strArgument.mid(5).toInt(&ok);
+ pluginName = QLatin1String("qmldbg_tcp");
+ } 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);
+ }
}
- block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block"));
-
if (ok) {
qQmlDebugServer = new QQmlDebugServer();
QQmlDebugServerThread *thread = new QQmlDebugServerThread;
qQmlDebugServer->d_func()->thread = thread;
qQmlDebugServer->moveToThread(thread);
thread->setPluginName(pluginName);
- thread->setPort(port, block);
+ thread->setPort(port, block, hostAddress);
thread->start();
if (block) {
diff --git a/src/qml/debugger/qqmldebugserverconnection_p.h b/src/qml/debugger/qqmldebugserverconnection_p.h
index ab9e7bd73f..920e82ed47 100644
--- a/src/qml/debugger/qqmldebugserverconnection_p.h
+++ b/src/qml/debugger/qqmldebugserverconnection_p.h
@@ -69,7 +69,7 @@ public:
virtual ~QQmlDebugServerConnection() {}
virtual void setServer(QQmlDebugServer *server) = 0;
- virtual void setPort(int port, bool bock) = 0;
+ virtual void setPort(int port, bool bock, const QString &hostaddress) = 0;
virtual bool isConnected() const = 0;
virtual void send(const QList<QByteArray> &messages) = 0;
virtual void disconnect() = 0;
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
index 67bec3577b..7f0bf7ca33 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/qml/debugger/qqmlenginedebugservice.cpp
@@ -67,7 +67,7 @@ QQmlEngineDebugService *QQmlEngineDebugService::instance()
}
QQmlEngineDebugService::QQmlEngineDebugService(QObject *parent)
- : QQmlDebugService(QStringLiteral("QDeclarativeEngine"), 1, parent),
+ : QQmlDebugService(QStringLiteral("QmlDebugger"), 1, parent),
m_watch(new QQmlWatcher(this)),
m_statesDelegate(0)
{
@@ -394,12 +394,10 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
QDataStream ds(message);
QByteArray type;
- ds >> type;
+ int queryId;
+ ds >> type >> queryId;
if (type == "LIST_ENGINES") {
- int queryId;
- ds >> queryId;
-
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("LIST_ENGINES_R");
@@ -416,9 +414,8 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
sendMessage(reply);
} else if (type == "LIST_OBJECTS") {
- int queryId;
int engineId = -1;
- ds >> queryId >> engineId;
+ ds >> engineId;
QQmlEngine *engine =
qobject_cast<QQmlEngine *>(QQmlDebugService::objectForId(engineId));
@@ -443,12 +440,11 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
sendMessage(reply);
} else if (type == "FETCH_OBJECT") {
- int queryId;
int objectId;
bool recurse;
bool dumpProperties = true;
- ds >> queryId >> objectId >> recurse >> dumpProperties;
+ ds >> objectId >> recurse >> dumpProperties;
QObject *object = QQmlDebugService::objectForId(objectId);
@@ -464,10 +460,9 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
sendMessage(reply);
} else if (type == "WATCH_OBJECT") {
- int queryId;
int objectId;
- ds >> queryId >> objectId;
+ ds >> objectId;
bool ok = m_watch->addWatch(queryId, objectId);
QByteArray reply;
@@ -476,11 +471,10 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
sendMessage(reply);
} else if (type == "WATCH_PROPERTY") {
- int queryId;
int objectId;
QByteArray property;
- ds >> queryId >> objectId >> property;
+ ds >> objectId >> property;
bool ok = m_watch->addWatch(queryId, objectId, property);
QByteArray reply;
@@ -489,11 +483,10 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
sendMessage(reply);
} else if (type == "WATCH_EXPR_OBJECT") {
- int queryId;
int debugId;
QString expr;
- ds >> queryId >> debugId >> expr;
+ ds >> debugId >> expr;
bool ok = m_watch->addWatch(queryId, debugId, expr);
QByteArray reply;
@@ -501,16 +494,17 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
sendMessage(reply);
} else if (type == "NO_WATCH") {
- int queryId;
+ bool ok = m_watch->removeWatch(queryId);
- ds >> queryId;
- m_watch->removeWatch(queryId);
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("NO_WATCH_R") << queryId << ok;
+ sendMessage(reply);
} else if (type == "EVAL_EXPRESSION") {
- int queryId;
int objectId;
QString expr;
- ds >> queryId >> objectId >> expr;
+ ds >> objectId >> expr;
QObject *object = QQmlDebugService::objectForId(objectId);
QQmlContext *context = qmlContext(object);
@@ -539,26 +533,43 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
bool isLiteralValue;
QString filename;
int line;
- ds >> objectId >> propertyName >> expr >> isLiteralValue;
- if (!ds.atEnd()) { // backward compatibility from 2.1, 2.2
- ds >> filename >> line;
- }
- setBinding(objectId, propertyName, expr, isLiteralValue, filename, line);
+ ds >> objectId >> propertyName >> expr >> isLiteralValue >>
+ filename >> line;
+ bool ok = setBinding(objectId, propertyName, expr, isLiteralValue,
+ filename, line);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("SET_BINDING_R") << queryId << ok;
+
+ sendMessage(reply);
} else if (type == "RESET_BINDING") {
int objectId;
QString propertyName;
ds >> objectId >> propertyName;
- resetBinding(objectId, propertyName);
+ bool ok = resetBinding(objectId, propertyName);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("RESET_BINDING_R") << queryId << ok;
+
+ sendMessage(reply);
} else if (type == "SET_METHOD_BODY") {
int objectId;
QString methodName;
QString methodBody;
ds >> objectId >> methodName >> methodBody;
- setMethodBody(objectId, methodName, methodBody);
+ bool ok = setMethodBody(objectId, methodName, methodBody);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
+
+ sendMessage(reply);
}
}
-void QQmlEngineDebugService::setBinding(int objectId,
+bool QQmlEngineDebugService::setBinding(int objectId,
const QString &propertyName,
const QVariant &expression,
bool isLiteralValue,
@@ -566,6 +577,7 @@ void QQmlEngineDebugService::setBinding(int objectId,
int line,
int column)
{
+ bool ok = true;
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
@@ -594,22 +606,23 @@ void QQmlEngineDebugService::setBinding(int objectId,
oldBinding->destroy();
binding->update();
} else {
+ ok = false;
qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
}
}
} else {
// not a valid property
- bool ok = false;
if (m_statesDelegate)
ok = m_statesDelegate->setBindingForInvalidProperty(object, propertyName, expression, isLiteralValue);
if (!ok)
qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
}
}
+ return ok;
}
-void QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyName)
+bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyName)
{
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
@@ -651,24 +664,25 @@ void QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyN
m_statesDelegate->resetBindingForInvalidProperty(object, propertyName);
}
}
+ return true;
}
-void QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, const QString &body)
+bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, const QString &body)
{
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
if (!object || !context || !context->engine())
- return;
+ return false;
QQmlContextData *contextData = QQmlContextData::get(context);
if (!contextData)
- return;
+ return false;
QQmlPropertyData dummy;
QQmlPropertyData *prop =
QQmlPropertyCache::property(context->engine(), object, method, dummy);
if (!prop || !prop->isVMEFunction())
- return;
+ return false;
QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
QList<QByteArray> paramNames = metaMethod.parameterNames();
@@ -690,6 +704,7 @@ void QQmlEngineDebugService::setMethodBody(int objectId, const QString &method,
int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
vmeMetaObject->setVmeMethod(prop->coreIndex, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber));
+ return true;
}
void QQmlEngineDebugService::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
@@ -729,7 +744,8 @@ void QQmlEngineDebugService::objectCreated(QQmlEngine *engine, QObject *object)
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("OBJECT_CREATED") << engineId << objectId;
+ //unique queryId -1
+ rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId;
sendMessage(reply);
}
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/qml/debugger/qqmlenginedebugservice_p.h
index f41063d7a3..19a5776e27 100644
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ b/src/qml/debugger/qqmlenginedebugservice_p.h
@@ -119,9 +119,9 @@ private:
QQmlObjectData objectData(QObject *);
QQmlObjectProperty propertyData(QObject *, int);
QVariant valueContents(const QVariant &defaultValue) const;
- void setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1, int column = 0);
- void resetBinding(int objectId, const QString &propertyName);
- void setMethodBody(int objectId, const QString &method, const QString &body);
+ bool setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1, int column = 0);
+ bool resetBinding(int objectId, const QString &propertyName);
+ bool setMethodBody(int objectId, const QString &method, const QString &body);
QList<QQmlEngine *> m_engines;
QQmlWatcher *m_watch;
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index 7a708456ba..2b4cafb615 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -54,12 +54,15 @@
//
#include <private/qqmldebugservice_p.h>
-#include <QtQml/qtqmlglobal.h>
+#include "qqmlexpression.h"
+
#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qmetaobject.h>
#include <QtCore/qmutex.h>
#include <QtCore/qvector.h>
#include <QtCore/qstringbuilder.h>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -194,47 +197,30 @@ struct QQmlBindingProfiler {
QQmlProfilerService::instance->endRange(QQmlProfilerService::Binding);
}
- void addDetail(const QString &details)
- {
- if (enabled)
- QQmlProfilerService::instance->rangeData(QQmlProfilerService::Binding,
- details);
- }
-\
bool enabled;
};
struct QQmlHandlingSignalProfiler {
- QQmlHandlingSignalProfiler()
+ QQmlHandlingSignalProfiler(const QMetaMethod &signal, QQmlExpression *expression)
{
enabled = QQmlProfilerService::instance
? QQmlProfilerService::instance->profilingEnabled() : false;
if (enabled) {
- QQmlProfilerService::instance->startRange(
- QQmlProfilerService::HandlingSignal);
+ QQmlProfilerService *service = QQmlProfilerService::instance;
+ service->startRange(QQmlProfilerService::HandlingSignal);
+ service->rangeData(QQmlProfilerService::HandlingSignal,
+ QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ")
+ + expression->expression());
+ service->rangeLocation(QQmlProfilerService::HandlingSignal,
+ expression->sourceFile(), expression->lineNumber(),
+ expression->columnNumber());
}
}
- void setSignalInfo(const QString &name, const QString &expression)
- {
- if (enabled)
- QQmlProfilerService::instance->rangeData(
- QQmlProfilerService::HandlingSignal,
- name % QLatin1String(": ") % expression);
- }
-
- void setLocation(const QString &file, int line, int column)
- {
- if (enabled)
- QQmlProfilerService::instance->rangeLocation(
- QQmlProfilerService::HandlingSignal, file, line, column);
- }
-
~QQmlHandlingSignalProfiler()
{
if (enabled)
- QQmlProfilerService::instance->endRange(
- QQmlProfilerService::HandlingSignal);
+ QQmlProfilerService::instance->endRange(QQmlProfilerService::HandlingSignal);
}
bool enabled;
@@ -243,22 +229,23 @@ struct QQmlHandlingSignalProfiler {
struct QQmlObjectCreatingProfiler {
QQmlObjectCreatingProfiler()
{
- QQmlProfilerService *instance = QQmlProfilerService::instance;
- enabled = instance ?
- instance->profilingEnabled() : false;
- if (enabled)
- instance->startRange(QQmlProfilerService::Creating);
+ enabled = QQmlProfilerService::instance
+ ? QQmlProfilerService::instance->profilingEnabled() : false;
+ if (enabled) {
+ QQmlProfilerService *service = QQmlProfilerService::instance;
+ service->startRange(QQmlProfilerService::Creating);
+ }
}
void setTypeName(const QString &typeName)
{
- if (enabled)
- QQmlProfilerService::instance->rangeData(
- QQmlProfilerService::Creating, typeName);
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ QQmlProfilerService::instance->rangeData(QQmlProfilerService::Creating, typeName);
}
void setLocation(const QUrl &url, int line, int column)
{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
if (enabled)
QQmlProfilerService::instance->rangeLocation(
QQmlProfilerService::Creating, url, line, column);
diff --git a/src/qml/debugger/qv8debugservice.cpp b/src/qml/debugger/qv8debugservice.cpp
index a6aeda31d5..7d54a59ac0 100644
--- a/src/qml/debugger/qv8debugservice.cpp
+++ b/src/qml/debugger/qv8debugservice.cpp
@@ -42,6 +42,7 @@
#include "qv8debugservice_p.h"
#include "qqmldebugservice_p_p.h"
#include <private/qjsconverter_impl_p.h>
+#include <private/qv4compiler_p.h>
#include <private/qv8engine_p.h>
#include <QtCore/QHash>
@@ -192,6 +193,7 @@ void QV8DebugService::init()
Q_D(QV8DebugService);
v8::Debug::SetMessageHandler2(DebugMessageHandler);
v8::Debug::SetDebugMessageDispatchHandler(DebugMessageDispatchHandler);
+ QV4Compiler::enableV4(false);
d->initializeMutex.unlock();
}
diff --git a/src/qml/debugger/qv8profilerservice.cpp b/src/qml/debugger/qv8profilerservice.cpp
index 6208676522..c75c258785 100644
--- a/src/qml/debugger/qv8profilerservice.cpp
+++ b/src/qml/debugger/qv8profilerservice.cpp
@@ -52,20 +52,19 @@ Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance)
class DebugServiceOutputStream : public v8::OutputStream
{
- QQmlDebugService &_service;
public:
- DebugServiceOutputStream(QQmlDebugService &service)
- : v8::OutputStream(),
- _service(service) {}
+ DebugServiceOutputStream()
+ : v8::OutputStream() {}
void EndOfStream() {}
WriteResult WriteAsciiChunk(char *rawData, int size)
{
QByteArray data;
QDataStream ds(&data, QIODevice::WriteOnly);
ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size);
- _service.sendMessage(data);
+ messages.append(data);
return kContinue;
}
+ QList<QByteArray> messages;
};
// convert to a QByteArray that can be sent to the debug client
@@ -267,16 +266,18 @@ void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType
v8::HandleScope scope;
v8::Local<v8::String> title = v8::String::New("");
- DebugServiceOutputStream outputStream(*q);
+ DebugServiceOutputStream outputStream;
const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType);
snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON);
+ QList<QByteArray> messages = outputStream.messages;
//indicate completion
QByteArray data;
QDataStream ds(&data, QIODevice::WriteOnly);
ds << (int)QV8ProfilerService::V8SnapshotComplete;
+ messages.append(data);
- q->sendMessage(data);
+ q->sendMessages(messages);
}
void QV8ProfilerServicePrivate::sendMessages()
@@ -285,16 +286,16 @@ void QV8ProfilerServicePrivate::sendMessages()
QList<QByteArray> messages;
for (int i = 0; i < m_data.count(); ++i)
- messages << m_data.at(i).toByteArray();
- q->sendMessages(messages);
+ messages.append(m_data.at(i).toByteArray());
m_data.clear();
//indicate completion
QByteArray data;
QDataStream ds(&data, QIODevice::WriteOnly);
ds << (int)QV8ProfilerService::V8Complete;
+ messages.append(data);
- q->sendMessage(data);
+ q->sendMessages(messages);
}
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index f575285ff6..f058f21e98 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -59,6 +59,10 @@
#include <private/qflagpointer_p.h>
+#if defined(Q_OS_QNX)
+#include <stdlib.h>
+#endif
+
QT_BEGIN_NAMESPACE
// Enable this to debug hash linking assumptions.
diff --git a/src/qml/qml/ftw/qqmlpool.cpp b/src/qml/qml/ftw/qqmlpool.cpp
index 6fd11d4b1e..64df87ada5 100644
--- a/src/qml/qml/ftw/qqmlpool.cpp
+++ b/src/qml/qml/ftw/qqmlpool.cpp
@@ -41,6 +41,10 @@
#include "qqmlpool_p.h"
+#ifdef Q_OS_QNX
+#include <malloc.h>
+#endif
+
// #define POOL_DEBUG
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlaccessors_p.h b/src/qml/qml/qqmlaccessors_p.h
index a603bede9f..8e67a58511 100644
--- a/src/qml/qml/qqmlaccessors_p.h
+++ b/src/qml/qml/qqmlaccessors_p.h
@@ -47,6 +47,10 @@
#include <QtCore/qhash.h>
#include <QtCore/QReadWriteLock>
+#ifdef Q_OS_QNX
+#include <stdint.h>
+#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index f43822ed0e..c4f48ef63d 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -193,8 +193,6 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
if (!updatingFlag()) {
QQmlBindingProfiler prof(m_url, m_lineNumber, m_columnNumber);
- if (prof.enabled)
- prof.addDetail(expression());
setUpdatingFlag(true);
QQmlAbstractExpression::DeleteWatcher watcher(this);
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index aa130d9493..f7d0c00a5c 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -174,13 +174,7 @@ int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
if (QQmlDebugService::isDebuggingEnabled())
QV8DebugService::instance()->signalEmitted(QString::fromAscii(m_signal.methodSignature().constData()));
- QQmlHandlingSignalProfiler prof;
- if (prof.enabled) {
- prof.setSignalInfo(QString::fromLatin1(m_signal.methodSignature().constData()),
- m_expression->expression());
- prof.setLocation(m_expression->sourceFile(), m_expression->lineNumber(),
- m_expression->columnNumber());
- }
+ QQmlHandlingSignalProfiler prof(m_signal, m_expression);
m_isEvaluating = true;
if (!m_paramsValid) {
@@ -233,7 +227,10 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method,
prop.setWritable(false);
} else {
QByteArray propType = type;
- if (t >= int(QVariant::UserType) || t == QMetaType::UnknownType || t == QMetaType::Void) {
+ if ((QMetaType::typeFlags(t) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) {
+ t = QVariant::Int;
+ propType = "int";
+ } else if (t == QMetaType::UnknownType) {
QByteArray scope;
QByteArray name;
int scopeIdx = propType.lastIndexOf("::");
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index c3b8152ce1..dec9911481 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -2217,7 +2217,7 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
//optimization for <Type>.<EnumValue> enum assignments
bool isEnumAssignment = false;
- if (prop->core.isEnum())
+ if (prop->core.isEnum() || prop->core.propType == QMetaType::Int)
COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, value, &isEnumAssignment));
if (isEnumAssignment) {
@@ -2485,7 +2485,7 @@ bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop,
if (v->value.isScript()) {
//optimization for <Type>.<EnumValue> enum assignments
- if (prop->core.isEnum()) {
+ if (prop->core.isEnum() || prop->core.propType == QMetaType::Int) {
bool isEnumAssignment = false;
COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, v, &isEnumAssignment));
if (isEnumAssignment) {
@@ -2515,8 +2515,9 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
QQmlScript::Value *v,
bool *isAssignment)
{
+ bool isIntProp = (prop->core.propType == QMetaType::Int) && !prop->core.isEnum();
*isAssignment = false;
- if (!prop->core.isEnum())
+ if (!prop->core.isEnum() && !isIntProp)
return true;
QMetaProperty mprop = obj->metaObject()->property(prop->index);
@@ -2528,6 +2529,17 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
if (!string.at(0).isUpper())
return true;
+ if (isIntProp) {
+ // Allow enum assignment to ints.
+ int enumval = evaluateEnum(string.toUtf8());
+ if (enumval != -1) {
+ v->type = Value::Literal;
+ v->value = QQmlScript::Variant((double)enumval);
+ *isAssignment = true;
+ }
+ return true;
+ }
+
QStringList parts = string.split(QLatin1Char('.'));
if (parts.count() != 2)
return true;
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 6cd5cf6cec..416178e3e1 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -829,7 +829,10 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
if (rv) {
QQmlData *ddata = QQmlData::get(rv);
Q_ASSERT(ddata);
+ //top level objects should never get JS ownership.
+ //if JS ownership is needed this needs to be explicitly undone (like in component.createObject())
ddata->indestructible = true;
+ ddata->explicitIndestructibleSet = true;
}
if (enginePriv->isDebugging && rv) {
@@ -1120,7 +1123,8 @@ void QQmlComponent::createObject(QQmlV8Function *args)
d->completeCreate();
Q_ASSERT(QQmlData::get(rv));
- QQmlData::get(rv)->setImplicitDestructible();
+ QQmlData::get(rv)->explicitIndestructibleSet = false;
+ QQmlData::get(rv)->indestructible = false;
if (!rv)
args->returnValue(v8::Null());
@@ -1255,10 +1259,6 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(v8::Handle<v8::
v8::Handle<v8::Value> args[] = { object, valuemap };
v8::Handle<v8::Function>::Cast(function)->Call(v8engine->global(), 2, args);
}
-
- QQmlData *ddata = QQmlData::get(toCreate);
- Q_ASSERT(ddata);
- ddata->setImplicitDestructible();
}
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index d10543bde5..97bc04b91d 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -146,7 +146,7 @@ public:
quint32 isJSContext:1;
quint32 isPragmaLibraryContext:1;
quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
- quint32 dummy:28;
+ quint32 dummy:27;
QQmlContext *publicContext;
// VME data that is constructing this context if any
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 7b99214f04..df5f7f8ee9 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -295,4 +295,18 @@ QList<QQmlDirParser::TypeInfo> QQmlDirParser::typeInfos() const
}
#endif
+QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
+{
+ return debug << qPrintable(QString("{%1 %2.%3}").arg(component.typeName)
+ .arg(component.majorVersion)
+ .arg(component.minorVersion));
+}
+
+QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
+{
+ return debug << qPrintable(QString("{%1 %2.%3}").arg(script.nameSpace)
+ .arg(script.majorVersion)
+ .arg(script.minorVersion));
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h
index 8c681309ac..f46e1781da 100644
--- a/src/qml/qml/qqmldirparser_p.h
+++ b/src/qml/qml/qqmldirparser_p.h
@@ -55,6 +55,7 @@
#include <QtCore/QUrl>
#include <QtCore/QHash>
+#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
@@ -160,6 +161,8 @@ private:
typedef QList<QQmlDirParser::Component> QQmlDirComponents;
typedef QList<QQmlDirParser::Script> QQmlDirScripts;
+QDebug &operator<< (QDebug &, const QQmlDirParser::Component &);
+QDebug &operator<< (QDebug &, const QQmlDirParser::Script &);
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp
index b69fa5da7a..86d9f9588d 100644
--- a/src/qml/qml/qqmlextensionplugin.cpp
+++ b/src/qml/qml/qqmlextensionplugin.cpp
@@ -97,7 +97,7 @@ QT_BEGIN_NAMESPACE
\code
TEMPLATE = lib
CONFIG += qt plugin
- QT += declarative
+ QT += qml
DESTDIR = com/nokia/TimeExample
TARGET = qmlqtimeexampleplugin
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 0c1fb3bd93..1224efdaac 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -117,7 +117,7 @@ public:
QList<QQmlError> *errors);
QString resolvedUri(const QString &dir_arg, QQmlImportDatabase *database);
- bool add(const QQmlDirComponents &qmldircomponentsnetwork,
+ QString add(const QQmlDirComponents &qmldircomponentsnetwork,
const QString& uri_arg, const QString& prefix,
int vmaj, int vmin, QQmlScript::Import::Type importType,
QQmlImportDatabase *database, QList<QQmlError> *errors);
@@ -493,7 +493,7 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba
return stableRelativePath;
}
-bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
+QString QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
const QString& uri_arg, const QString& prefix, int vmaj, int vmin,
QQmlScript::Import::Type importType,
QQmlImportDatabase *database, QList<QQmlError> *errors)
@@ -540,7 +540,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, database);
if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return false;
+ return QString();
break;
}
}
@@ -564,7 +564,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, database);
if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return false;
+ return QString();
break;
}
}
@@ -586,7 +586,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
url = QUrl::fromLocalFile(absolutePath).toString();
uri = resolvedUri(dir, database);
if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return false;
+ return QString();
break;
}
}
@@ -604,7 +604,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg));
errors->prepend(error);
}
- return false;
+ return QString();
}
} else {
if (importType == QQmlScript::Import::File && qmldircomponents.isEmpty()) {
@@ -619,14 +619,14 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
error.setUrl(QUrl(importUrl));
errors->prepend(error);
}
- return false; // local import dirs must exist
+ return QString(); // local import dirs must exist
}
uri = resolvedUri(dir, database);
if (uri.endsWith(Slash))
uri.chop(1);
if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) {
if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,&qmldirscripts,errors))
- return false;
+ return QString();
}
} else {
if (prefix.isEmpty()) {
@@ -642,7 +642,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
error.setUrl(QUrl(importUrl));
errors->prepend(error);
}
- return false;
+ return QString();
}
}
}
@@ -669,7 +669,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin));
errors->prepend(error);
}
- return false;
+ return QString();
}
}
@@ -686,7 +686,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
QQmlError error;
error.setDescription(QQmlImportDatabase::tr("\"%1\" is ambiguous. Found in %2 and in %3").arg(uri).arg(url).arg(it->url));
errors->prepend(error);
- return false;
+ return QString();
}
}
@@ -716,7 +716,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
s->imports.prepend(data);
- return true;
+ return data.url;
}
bool QQmlImportsPrivate::find(const QString& type, int *vmajor, int *vminor, QQmlType** type_return,
@@ -874,9 +874,11 @@ QQmlImportDatabase::~QQmlImportDatabase()
The \a prefix may be empty, in which case the import location is considered for
unqualified types.
+ Returns the resolved URL of the import on success.
+
The base URL must already have been set with Import::setBaseUrl().
*/
-bool QQmlImports::addImport(QQmlImportDatabase *importDb,
+QString QQmlImports::addImport(QQmlImportDatabase *importDb,
const QString& uri, const QString& prefix, int vmaj, int vmin,
QQmlScript::Import::Type importType,
const QQmlDirComponents &qmldircomponentsnetwork,
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index ff19510525..422f2429a0 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -93,7 +93,7 @@ public:
QQmlType** type_return, QString* url_return,
int *version_major, int *version_minor) const;
- bool addImport(QQmlImportDatabase *,
+ QString addImport(QQmlImportDatabase *,
const QString& uri, const QString& prefix, int vmaj, int vmin,
QQmlScript::Import::Type importType,
const QQmlDirComponents &qmldircomponentsnetwork,
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index aa9777d89e..fad2ae2f28 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -293,8 +293,9 @@ void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i)
if (result) {
QQmlData *ddata = QQmlData::get(result);
Q_ASSERT(ddata);
+ //see QQmlComponent::beginCreate for explanation of indestructible
ddata->indestructible = true;
-
+ ddata->explicitIndestructibleSet = true;
q->setInitialState(result);
}
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 5b80f57d01..4af08c28bf 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -512,7 +512,7 @@ QObject *QQmlType::create() const
d->m_newFunc(rv);
if (rv && !d->m_metaObjects.isEmpty())
- (void *)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
+ (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
return rv;
}
@@ -525,7 +525,7 @@ void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) con
d->m_newFunc(rv);
if (rv && !d->m_metaObjects.isEmpty())
- (void *)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
+ (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
*out = rv;
*memory = ((char *)rv) + d->m_allocationSize;
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index afab665ea4..4a1eb79213 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -674,7 +674,13 @@ QStringList QQmlPropertyCache::propertyNames() const
return keys;
}
-static int EnumType(const QMetaObject *meta, const QByteArray &str)
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+static int EnumType(const QMetaObject *metaobj, const QByteArray &str)
{
QByteArray scope;
QByteArray name;
@@ -685,6 +691,11 @@ static int EnumType(const QMetaObject *meta, const QByteArray &str)
} else {
name = str;
}
+ const QMetaObject *meta;
+ if (scope == "Qt")
+ meta = StaticQtMetaObject::get();
+ else
+ meta = metaobj;
for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
QMetaEnum m = meta->enumerator(i);
if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
@@ -727,12 +738,14 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
for (int ii = 0; ii < argc; ++ii) {
int type = m.parameterType(ii);
- if (type == QVariant::Invalid) {
+ if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration)
+ type = QVariant::Int;
+ else if (type == QMetaType::UnknownType) {
if (argTypeNames.isEmpty())
argTypeNames = m.parameterTypes();
type = EnumType(object->metaObject(), argTypeNames.at(ii));
}
- if (type == QVariant::Invalid) {
+ if (type == QMetaType::UnknownType) {
if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
free(args);
return 0;
@@ -754,12 +767,14 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
for (int ii = 0; ii < argc; ++ii) {
int type = m.parameterType(ii);
- if (type == QVariant::Invalid) {
+ if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration)
+ type = QVariant::Int;
+ else if (type == QMetaType::UnknownType) {
if (argTypeNames.isEmpty())
argTypeNames = m.parameterTypes();
type = EnumType(object->metaObject(), argTypeNames.at(ii));
}
- if (type == QVariant::Invalid) {
+ if (type == QMetaType::UnknownType) {
if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
return 0;
}
diff --git a/src/qml/qml/qqmlstringconverters.cpp b/src/qml/qml/qqmlstringconverters.cpp
index 473097fab0..04b63ea7cd 100644
--- a/src/qml/qml/qqmlstringconverters.cpp
+++ b/src/qml/qml/qqmlstringconverters.cpp
@@ -128,6 +128,9 @@ QDateTime QQmlStringConverters::dateTimeFromString(const QString &s, bool *ok)
{
QDateTime d = QDateTime::fromString(s, Qt::ISODate);
if (ok) *ok = d.isValid();
+ // V8 never parses a date string as local time. For consistency do the same here.
+ if (d.timeSpec() == Qt::LocalTime)
+ d.setTimeSpec(Qt::UTC);
return d;
}
#endif // QT_NO_DATESTRING
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 781915e23e..abe2c0bfa4 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1558,7 +1558,6 @@ void QQmlTypeData::dataReceived(const QByteArray &data)
ref.qualifier = import.qualifier;
ref.script = blob;
m_scripts << ref;
-
}
}
@@ -1657,8 +1656,8 @@ void QQmlTypeData::resolveTypes()
import.extractVersion(&vmaj, &vmin);
QList<QQmlError> errors;
- if (!m_imports.addImport(importDatabase, import.uri, import.qualifier,
- vmaj, vmin, import.type, qmldircomponentsnetwork, &errors)) {
+ if (m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin,
+ import.type, qmldircomponentsnetwork, &errors).isNull()) {
QQmlError error;
if (errors.size()) {
error = errors.takeFirst();
@@ -1859,8 +1858,9 @@ void QQmlScriptBlob::dataReceived(const QByteArray &data)
import.extractVersion(&vmaj, &vmin);
QList<QQmlError> errors;
- if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin,
- import.type, QQmlDirComponents(), &errors)) {
+ QString importUrl = m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin,
+ import.type, QQmlDirComponents(), &errors);
+ if (importUrl.isNull()) {
QQmlError error = errors.takeFirst();
// description should be set by addImport().
error.setUrl(m_imports.baseUrl());
@@ -1871,6 +1871,22 @@ void QQmlScriptBlob::dataReceived(const QByteArray &data)
setError(errors);
return;
}
+
+ // Does this library contain any scripts?
+ QUrl libraryUrl(importUrl);
+ const QQmlDirParser *dirParser = typeLoader()->qmlDirParser(libraryUrl.path() + QLatin1String("qmldir"));
+ foreach (const QQmlDirParser::Script &script, dirParser->scripts()) {
+ QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
+ QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
+ addDependency(blob);
+
+ ScriptReference ref;
+ ref.location = import.location.start;
+ ref.qualifier = script.nameSpace;
+ ref.nameSpace = import.qualifier;
+ ref.script = blob;
+ m_scripts << ref;
+ }
}
}
}
@@ -1902,11 +1918,20 @@ void QQmlScriptBlob::done()
m_scriptData->urlString = finalUrlString();
m_scriptData->importCache = new QQmlTypeNameCache();
- for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
- const ScriptReference &script = m_scripts.at(ii);
+ QSet<QString> ns;
+
+ for (int scriptIndex = 0; !isError() && scriptIndex < m_scripts.count(); ++scriptIndex) {
+ const ScriptReference &script = m_scripts.at(scriptIndex);
m_scriptData->scripts.append(script.script);
- m_scriptData->importCache->add(script.qualifier, ii);
+
+ if (!script.nameSpace.isNull()) {
+ if (!ns.contains(script.nameSpace)) {
+ ns.insert(script.nameSpace);
+ m_scriptData->importCache->add(script.nameSpace);
+ }
+ }
+ m_scriptData->importCache->add(script.qualifier, scriptIndex, script.nameSpace);
}
m_imports.populateCache(m_scriptData->importCache, engine);
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index c8c2756bd5..319b2e7a10 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -390,6 +390,7 @@ public:
QQmlScript::Location location;
QString qualifier;
+ QString nameSpace;
QQmlScriptBlob *script;
};
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 6309335e59..352684ed5e 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -829,7 +829,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
bindValues.push(binding);
binding->m_mePtr = &bindValues.top();
- Q_ASSERT(binding->propertyIndex() == property);
+ Q_ASSERT(binding->propertyIndex() == (property & 0xFF00FFFF));
Q_ASSERT(binding->object() == target);
binding->addToObject();
diff --git a/src/qml/qml/qqmlwatcher.cpp b/src/qml/qml/qqmlwatcher.cpp
index 500185762f..4eaa3d2c2a 100644
--- a/src/qml/qml/qqmlwatcher.cpp
+++ b/src/qml/qml/qqmlwatcher.cpp
@@ -166,13 +166,14 @@ bool QQmlWatcher::addWatch(int id, quint32 objectId, const QString &expr)
return false;
}
-void QQmlWatcher::removeWatch(int id)
+bool QQmlWatcher::removeWatch(int id)
{
if (!m_proxies.contains(id))
- return;
+ return false;
QList<QPointer<QQmlWatchProxy> > proxies = m_proxies.take(id);
qDeleteAll(proxies);
+ return true;
}
void QQmlWatcher::addPropertyWatch(int id, QObject *object, quint32 debugId, const QMetaProperty &property)
diff --git a/src/qml/qml/qqmlwatcher_p.h b/src/qml/qml/qqmlwatcher_p.h
index 70dc9d468c..3ca2c83777 100644
--- a/src/qml/qml/qqmlwatcher_p.h
+++ b/src/qml/qml/qqmlwatcher_p.h
@@ -77,7 +77,7 @@ public:
bool addWatch(int id, quint32 objectId, const QByteArray &property);
bool addWatch(int id, quint32 objectId, const QString &expr);
- void removeWatch(int id);
+ bool removeWatch(int id);
Q_SIGNALS:
void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index df1712976c..56743eb915 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1384,7 +1384,7 @@ void QQmlXMLHttpRequest::readEncoding()
if (header.first == "content-type") {
int separatorIdx = header.second.indexOf(';');
if (separatorIdx == -1) {
- m_mime == header.second;
+ m_mime = header.second;
} else {
m_mime = header.second.mid(0, separatorIdx);
int charsetIdx = header.second.indexOf("charset=");
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp
index 38a3acafa2..0cd6ffd082 100644
--- a/src/qml/qml/v4/qv4bindings.cpp
+++ b/src/qml/qml/v4/qv4bindings.cpp
@@ -1153,6 +1153,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertColorToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertObjectToBool, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ // ### NaN
+ if (src.isUndefined())
+ output.setUndefined();
+ else
+ output.setbool(src.getQObject() != 0);
+ }
+ QML_V4_END_INSTR(ConvertObjectToBool, unaryop)
+
+ QML_V4_BEGIN_INSTR(ConvertNullToObject, unaryop)
+ {
+ Register &output = registers[instr->unaryop.output];
+ output.setQObject(0);
+ }
+ QML_V4_END_INSTR(ConvertNullToObject, unaryop)
+
QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
{
const Register &src = registers[instr->unaryop.src];
diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp
index 09b0f3861b..c9495e8987 100644
--- a/src/qml/qml/v4/qv4compiler.cpp
+++ b/src/qml/qml/v4/qv4compiler.cpp
@@ -54,7 +54,6 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP)
DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER)
-DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL)
DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
DEFINE_BOOL_CONFIG_OPTION(qmlBindingsTestEnv, QML_BINDINGS_TEST)
@@ -958,6 +957,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break;
case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break;
+ case IR::ObjectType: opcode = V4Instr::ConvertObjectToBool; break;
default: break;
} // switch
} else if (targetTy == IR::IntType) {
@@ -1010,6 +1010,11 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
case IR::StringType: opcode = V4Instr::ConvertStringToColor; break;
default: break;
} // switch
+ } else if (targetTy == IR::ObjectType) {
+ switch (sourceTy) {
+ case IR::NullType: opcode = V4Instr::ConvertNullToObject; break;
+ default: break;
+ } // switch
}
if (opcode != V4Instr::Noop) {
V4Instr conv;
@@ -1354,9 +1359,6 @@ int QV4Compiler::compile(const Expression &expression, QQmlEnginePrivate *engine
{
if (!expression.expression.asAST()) return false;
- if (!qmlExperimental() && expression.property->isValueTypeSubProperty)
- return -1;
-
if (qmlDisableOptimizer() || !qmlEnableV4)
return -1;
diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp
index 1ed8bd245e..cb6ff40589 100644
--- a/src/qml/qml/v4/qv4instruction.cpp
+++ b/src/qml/qml/v4/qv4instruction.cpp
@@ -189,6 +189,12 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertColorToString:
INSTR_DUMP << "\t" << "ConvertColorToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertObjectToBool:
+ INSTR_DUMP << "\t" << "ConvertObjectToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
+ case V4Instr::ConvertNullToObject:
+ INSTR_DUMP << "\t" << "ConvertNullToObject" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ResolveUrl:
INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h
index d6c790e46f..239cb362cc 100644
--- a/src/qml/qml/v4/qv4instruction_p.h
+++ b/src/qml/qml/v4/qv4instruction_p.h
@@ -98,6 +98,8 @@ QT_BEGIN_NAMESPACE
F(ConvertUrlToString, unaryop) \
F(ConvertColorToBool, unaryop) \
F(ConvertColorToString, unaryop) \
+ F(ConvertObjectToBool, unaryop) \
+ F(ConvertNullToObject, unaryop) \
F(ResolveUrl, unaryop) \
F(MathSinReal, unaryop) \
F(MathCosReal, unaryop) \
diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp
index 481b23eb4a..ea4d1afbbc 100644
--- a/src/qml/qml/v4/qv4irbuilder.cpp
+++ b/src/qml/qml/v4/qv4irbuilder.cpp
@@ -428,7 +428,7 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
if (r.isValid()) {
if (r.type) {
_expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column);
- } else if (r.importNamespace) {
+ } /*else if (r.importNamespace) {
QQmlMetaType::ModuleApiInstance *moduleApi = m_expression->importCache->moduleApi(r.importNamespace);
if (moduleApi) {
if (moduleApi->qobjectCallback) {
@@ -439,7 +439,7 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
if (moduleApi->qobjectApi)
_expr.code = _block->MODULE_OBJECT(name, moduleApi->qobjectApi->metaObject(), IR::Name::MemberStorage, line, column);
}
- }
+ }*/ //### we can't create the actual QObject here, as we may be running in a thread (can be reenabled once QTBUG-24894 is handled)
// We don't support anything else
} else {
bool found = false;
diff --git a/src/qml/qml/v8/qjsconverter_impl_p.h b/src/qml/qml/v8/qjsconverter_impl_p.h
index 10b8ab5fae..c2775df7f5 100644
--- a/src/qml/qml/v8/qjsconverter_impl_p.h
+++ b/src/qml/qml/v8/qjsconverter_impl_p.h
@@ -44,6 +44,10 @@
#ifndef QJSCONVERTER_IMPL_P_H
#define QJSCONVERTER_IMPL_P_H
+#ifdef Q_OS_QNX
+#include <malloc.h>
+#endif
+
QT_BEGIN_NAMESPACE
extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str);
diff --git a/src/qml/qml/v8/qjsvalue.cpp b/src/qml/qml/v8/qjsvalue.cpp
index 4471e68a61..6ecb97d2e5 100644
--- a/src/qml/qml/v8/qjsvalue.cpp
+++ b/src/qml/qml/v8/qjsvalue.cpp
@@ -428,7 +428,7 @@ quint32 QJSValue::toUInt() const
\table
\header \li Input Type \li Result
\row \li Undefined \li An invalid QVariant.
- \row \li Null \li An invalid QVariant.
+ \row \li Null \li A QVariant containing a null pointer (QMetaType::VoidStar).
\row \li Boolean \li A QVariant containing the value of the boolean.
\row \li Number \li A QVariant containing the value of the number.
\row \li String \li A QVariant containing the value of the string.
diff --git a/src/qml/qml/v8/qjsvalue_impl_p.h b/src/qml/qml/v8/qjsvalue_impl_p.h
index fbddcfa5ba..8d22204843 100644
--- a/src/qml/qml/v8/qjsvalue_impl_p.h
+++ b/src/qml/qml/v8/qjsvalue_impl_p.h
@@ -281,7 +281,7 @@ QVariant QJSValuePrivate::toVariant() const
case CNumber:
return QVariant(u.m_number);
case CNull:
- return QVariant();
+ return QVariant(QMetaType::VoidStar, 0);
case CUndefined:
return QVariant();
case JSValue:
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 0cd5d0ad6c..9c570d756b 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1061,7 +1061,9 @@ v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args)
QObject *obj = component.beginCreate(effectiveContext);
if (obj) {
- QQmlData::get(obj, true)->setImplicitDestructible();
+ QQmlData::get(obj, true)->explicitIndestructibleSet = false;
+ QQmlData::get(obj)->indestructible = false;
+
obj->setParent(parentArg);
@@ -1084,7 +1086,7 @@ v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args)
}
/*!
-\qmlmethod object Qt::createComponent(url, mode)
+\qmlmethod object Qt::createComponent(url, mode, parent)
Returns a \l Component object created using the QML file at the specified \a url,
or \c null if an empty string was given.
@@ -1099,6 +1101,9 @@ will be \c Component.Loading while it is loading. The status will change to
\c Component.Ready if the component loads successfully, or \c Component.Error
if loading fails.
+If the optional \a parent parameter is given, it should refer to the object
+that will become the parent for the created \l Component object.
+
Call \l {Component::createObject()}{Component.createObject()} on the returned
component to create an object instance of the component.
@@ -1114,7 +1119,8 @@ use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
v8::Handle<v8::Value> createComponent(const v8::Arguments &args)
{
const char *invalidArgs = "Qt.createComponent(): Invalid arguments";
- if (args.Length() < 1 || args.Length() > 2)
+ const char *invalidParent = "Qt.createComponent(): Invalid parent object";
+ if (args.Length() < 1 || args.Length() > 3)
V8THROW_ERROR(invalidArgs);
QV8Engine *v8engine = V8ENGINE();
@@ -1131,21 +1137,46 @@ v8::Handle<v8::Value> createComponent(const v8::Arguments &args)
return v8::Null();
QQmlComponent::CompilationMode compileMode = QQmlComponent::PreferSynchronous;
- if (args.Length() == 2) {
+
+ // Default to engine parent; this will be removed in the near future (QTBUG-24841)
+ QObject *parentArg = engine;
+
+ unsigned consumedCount = 1;
+ if (args.Length() > 1) {
+ const v8::Local<v8::Value> &lastArg = args[args.Length()-1];
+
+ // The second argument could be the mode enum
if (args[1]->IsInt32()) {
int mode = args[1]->Int32Value();
if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous))
V8THROW_ERROR(invalidArgs);
compileMode = QQmlComponent::CompilationMode(mode);
+ consumedCount += 1;
} else {
- V8THROW_ERROR(invalidArgs);
+ // The second argument could be the parent only if there are exactly two args
+ if ((args.Length() != 2) || !(lastArg->IsObject() || lastArg->IsNull()))
+ V8THROW_ERROR(invalidArgs);
+ }
+
+ if (consumedCount < args.Length()) {
+ if (lastArg->IsObject()) {
+ parentArg = v8engine->toQObject(lastArg);
+ if (!parentArg)
+ V8THROW_ERROR(invalidParent);
+ } else if (lastArg->IsNull()) {
+ parentArg = 0;
+ } else {
+ V8THROW_ERROR(invalidParent);
+ }
}
}
QUrl url = context->resolvedUrl(QUrl(arg));
- QQmlComponent *c = new QQmlComponent(engine, url, compileMode, engine);
+ QQmlComponent *c = new QQmlComponent(engine, url, compileMode, parentArg);
QQmlComponentPrivate::get(c)->creationContext = effectiveContext;
- QQmlData::get(c, true)->setImplicitDestructible();
+ QQmlData::get(c, true)->explicitIndestructibleSet = false;
+ QQmlData::get(c)->indestructible = false;
+
return v8engine->newQObject(c);
}
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index f0df025541..678f9aa3ee 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -1368,7 +1368,8 @@ v8::Handle<v8::Value> QV8Engine::variantToJS(const QVariant &value)
}
// Converts a JS value to a QVariant.
-// Null, Undefined -> QVariant() (invalid)
+// Undefined -> QVariant() (invalid)
+// Null -> QVariant((void*)0)
// Boolean -> QVariant(bool)
// Number -> QVariant(double)
// String -> QVariant(QString)
@@ -1379,8 +1380,10 @@ v8::Handle<v8::Value> QV8Engine::variantToJS(const QVariant &value)
QVariant QV8Engine::variantFromJS(v8::Handle<v8::Value> value)
{
Q_ASSERT(!value.IsEmpty());
- if (value->IsNull() || value->IsUndefined())
+ if (value->IsUndefined())
return QVariant();
+ if (value->IsNull())
+ return QVariant(QMetaType::VoidStar, 0);
if (value->IsBoolean())
return value->ToBoolean()->Value();
if (value->IsInt32())
diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro
index 97b3788dcd..4dd21c6110 100644
--- a/src/qmldevtools/qmldevtools.pro
+++ b/src/qmldevtools/qmldevtools.pro
@@ -17,4 +17,4 @@ HEADERS += qtqmldevtoolsversion.h
unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES = QtCore
-include($$QT.qml.sources/qml/parser/parser.pri)
+include(../qml/qml/parser/parser.pri)
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index b1c99d2739..6df36d20cb 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -4,7 +4,7 @@ TARGET = QtQuickTest
QPRO_PWD = $$PWD
CONFIG += module
-CONFIG += dll warn_on declarative_debug
+CONFIG += dll warn_on
MODULE_PRI += ../../modules/qt_qmltest.pri
QT += testlib testlib-private qml quick gui
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index f8e5e3c57f..a605b9ce6d 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -63,6 +63,10 @@
#include <private/qv8domerrors_p.h>
#include <QtCore/qnumeric.h>
+#ifdef Q_OS_QNX
+#include <ctype.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
\qmlclass Context2D QQuickContext2D
diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp
index 46f85417d2..27efebca0c 100644
--- a/src/quick/items/qquickaccessibleattached.cpp
+++ b/src/quick/items/qquickaccessibleattached.cpp
@@ -144,6 +144,10 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
// Enable accessibility for items with accessible content. This also
// enables accessibility for the ancestors of souch items.
item->d_func()->setAccessibleFlagAndListener();
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessibleEvent ev(item, QAccessible::ObjectCreated);
+ QAccessible::updateAccessibility(&ev);
+#endif
}
QQuickAccessibleAttached::~QQuickAccessibleAttached()
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index 129c3ef240..419f21a4b3 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -85,6 +85,10 @@ public:
if (name != m_name) {
m_name = name;
emit nameChanged();
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessibleEvent ev(parent(), QAccessible::NameChanged);
+ QAccessible::updateAccessibility(&ev);
+#endif
}
}
@@ -94,6 +98,10 @@ public:
if (m_description != description) {
m_description = description;
emit descriptionChanged();
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessibleEvent ev(parent(), QAccessible::DescriptionChanged);
+ QAccessible::updateAccessibility(&ev);
+#endif
}
}
diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp
index cd3bbbfa2a..a11f68f709 100644
--- a/src/quick/items/qquickcanvas.cpp
+++ b/src/quick/items/qquickcanvas.cpp
@@ -306,6 +306,8 @@ QQuickCanvasPrivate::QQuickCanvasPrivate()
, windowManager(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
+ , persistentGLContext(false)
+ , persistentSceneGraph(false)
, renderTarget(0)
, renderTargetId(0)
, incubationController(0)
@@ -325,6 +327,7 @@ void QQuickCanvasPrivate::init(QQuickCanvas *c)
rootItem = new QQuickRootItem;
QQuickItemPrivate *rootItemPrivate = QQuickItemPrivate::get(rootItem);
rootItemPrivate->canvas = q;
+ rootItemPrivate->canvasRefCount = 1;
rootItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
// In the absence of a focus in event on some platforms assume the window will
@@ -536,7 +539,7 @@ void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
q->sendEvent(oldActiveFocusItem, &event);
QQuickItem *afi = oldActiveFocusItem;
- while (afi != scope) {
+ while (afi && afi != scope) {
if (QQuickItemPrivate::get(afi)->activeFocus) {
QQuickItemPrivate::get(afi)->activeFocus = false;
changed << afi;
@@ -548,27 +551,12 @@ void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
if (item != rootItem && !(options & DontChangeSubFocusItem)) {
QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
- // Correct focus chain in scope
- if (oldSubFocusItem) {
- QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
- while (sfi != scope) {
- QQuickItemPrivate::get(sfi)->subFocusItem = 0;
- sfi = sfi->parentItem();
- }
- }
- {
- scopePrivate->subFocusItem = item;
- QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
- while (sfi != scope) {
- QQuickItemPrivate::get(sfi)->subFocusItem = item;
- sfi = sfi->parentItem();
- }
- }
-
if (oldSubFocusItem) {
QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
changed << oldSubFocusItem;
}
+
+ QQuickItemPrivate::get(item)->updateSubFocusItem(scope, true);
}
if (!(options & DontChangeFocusProperty)) {
@@ -647,7 +635,7 @@ void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
q->sendEvent(oldActiveFocusItem, &event);
QQuickItem *afi = oldActiveFocusItem;
- while (afi != scope) {
+ while (afi && afi != scope) {
if (QQuickItemPrivate::get(afi)->activeFocus) {
QQuickItemPrivate::get(afi)->activeFocus = false;
changed << afi;
@@ -658,20 +646,13 @@ void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
if (item != rootItem && !(options & DontChangeSubFocusItem)) {
QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
- // Correct focus chain in scope
- if (oldSubFocusItem) {
- QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
- while (sfi != scope) {
- QQuickItemPrivate::get(sfi)->subFocusItem = 0;
- sfi = sfi->parentItem();
- }
- }
- scopePrivate->subFocusItem = 0;
-
if (oldSubFocusItem && !(options & DontChangeFocusProperty)) {
QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
changed << oldSubFocusItem;
}
+
+ QQuickItemPrivate::get(item)->updateSubFocusItem(scope, false);
+
} else if (!(options & DontChangeFocusProperty)) {
QQuickItemPrivate::get(item)->focus = false;
changed << item;
@@ -750,6 +731,55 @@ void QQuickCanvasPrivate::cleanup(QSGNode *n)
reparent the items to the root item or to an existing item in the scene.
For easily displaying a scene from a QML file, see \l{QQuickView}.
+
+
+ \section1 Scene Graph and Rendering
+
+ The QQuickCanvas uses a scene graph on top of OpenGL to render. This scene graph is disconnected
+ from the QML scene and potentially lives in another thread, depending on the platform
+ implementation. Since the rendering scene graph lives independently from the QML scene, it can
+ also be completely released without affecting the state of the QML scene.
+
+ The sceneGraphInitialized() signal is emitted on the rendering thread before the QML scene is
+ rendered to the screen for the first time. If the rendering scene graph has been released
+ the signal will be emitted again before the next frame is rendered.
+
+ Rendering is done by first copying the QML scene's state into the rendering scene graph. This is
+ done by calling QQuickItem::updatePaintNode() functions on all items that have changed. This phase
+ is run on the rendering thread with the GUI thread blocked, when a separate rendering thread
+ is being used. The scene can then be rendered.
+
+ Before the scene graph is rendered, the beforeRendering() signal is emitted. The OpenGL context
+ is bound at this point and the application is free to do its own rendering. Also
+ make sure to disable the clearing of the color buffer, using setClearBeforeRendering(). The
+ default clear color is white and can be changed with setClearColor(). After the scene has
+ been rendered, the afterRendering() signal is emitted. The application can use this to render
+ OpenGL on top of a QML application. Once the frame is fully done and has been swapped,
+ the frameSwapped() signal is emitted.
+
+ While the scene graph is being rendered on the rendering thread, the GUI will process animations
+ for the next frame. This means that as long as users are not using scene graph API
+ directly, the added complexity of a rendering thread can be completely ignored.
+
+ When a QQuickCanvas is programatically hidden with hide() or setVisible(false), it will
+ stop rendering and its scene graph and OpenGL context might be released. The
+ sceneGraphInvalidated() signal will be emitted when this happens.
+
+ \warning It is crucial that OpenGL operations and interaction with the scene graph happens
+ exclusively on the rendering thread, primarily during the updatePaintNode() phase.
+
+ \warning As signals related to rendering might be emitted from the rendering thread,
+ connections should be made using Qt::DirectConnection
+
+
+ \section1 Resource Management
+
+ QML will typically try to cache images, scene graph nodes, etc to improve performance, but in
+ some low-memory scenarios it might be required to aggressively release these resources. The
+ releaseResources() can be used to force clean up of certain resources. Calling releaseResources()
+ may result in the entire scene graph and its OpenGL context being deleted. The
+ sceneGraphInvalidated() signal will be emitted when this happens.
+
*/
QQuickCanvas::QQuickCanvas(QWindow *parent)
: QWindow(*(new QQuickCanvasPrivate), parent)
@@ -771,11 +801,6 @@ QQuickCanvas::~QQuickCanvas()
d->windowManager->canvasDestroyed(this);
- // ### should we change ~QQuickItem to handle this better?
- // manually cleanup for the root item (item destructor only handles these when an item is parented)
- QQuickItemPrivate *rootItemPrivate = QQuickItemPrivate::get(d->rootItem);
- rootItemPrivate->removeFromDirtyList();
-
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete d->incubationController; d->incubationController = 0;
@@ -786,6 +811,15 @@ QQuickCanvas::~QQuickCanvas()
/*!
This function tries to release redundant resources currently held by the QML scene.
+
+ Calling this function might result in the scene graph and the OpenGL context used
+ for rendering being released to release graphics memory. If this happens, the
+ sceneGraphInvalidated() signal will be called, allowing users to clean up their
+ own graphics resources. The setPersistentOpenGLContext() and setPersistentSceneGraph()
+ functions can be used to prevent this from happening, if handling the cleanup is
+ not feasible in the application, at the cost of higher memory usage.
+
+ \sa sceneGraphInvalidated(), setPersistentOpenGLContext(), setPersistentSceneGraph().
*/
void QQuickCanvas::releaseResources()
@@ -798,6 +832,69 @@ void QQuickCanvas::releaseResources()
/*!
+ Controls whether the OpenGL context can be released as a part of a call to
+ releaseResources().
+
+ The OpenGL context might still be released when the user makes an explicit
+ call to hide().
+
+ \sa setPersistentSceneGraph()
+ */
+
+void QQuickCanvas::setPersistentOpenGLContext(bool persistent)
+{
+ Q_D(QQuickCanvas);
+ d->persistentGLContext = persistent;
+}
+
+
+/*!
+ Returns whether the OpenGL context can be released as a part of a call to
+ releaseResources().
+ */
+
+bool QQuickCanvas::isPersistentOpenGLContext() const
+{
+ Q_D(const QQuickCanvas);
+ return d->persistentGLContext;
+}
+
+
+
+/*!
+ Controls whether the scene graph nodes and resources can be released as a
+ part of a call to releaseResources().
+
+ The scene graph nodes and resources might still be released when the user
+ makes an explicit call to hide().
+
+ \sa setPersistentOpenGLContext()
+ */
+
+void QQuickCanvas::setPersistentSceneGraph(bool persistent)
+{
+ Q_D(QQuickCanvas);
+ d->persistentSceneGraph = persistent;
+}
+
+
+
+/*!
+ Returns whether the scene graph nodes and resources can be released as a part
+ of a call to releaseResources().
+ */
+
+bool QQuickCanvas::isPersistentSceneGraph() const
+{
+ Q_D(const QQuickCanvas);
+ return d->persistentSceneGraph;
+}
+
+
+
+
+
+/*!
Returns the invisible root item of the scene.
A QQuickCanvas always has a single invisible root item. To add items to this canvas,
@@ -1618,6 +1715,7 @@ void QQuickCanvasPrivate::cleanupNodesOnShutdown(QQuickItem *item)
if (p->extra.isAllocated()) {
p->extra->opacityNode = 0;
p->extra->clipNode = 0;
+ p->extra->rootNode = 0;
}
p->groupNode = 0;
diff --git a/src/quick/items/qquickcanvas.h b/src/quick/items/qquickcanvas.h
index 4ac9509896..787bb7e3c7 100644
--- a/src/quick/items/qquickcanvas.h
+++ b/src/quick/items/qquickcanvas.h
@@ -114,6 +114,12 @@ public:
void setClearColor(const QColor &color);
QColor clearColor() const;
+ void setPersistentOpenGLContext(bool persistent);
+ bool isPersistentOpenGLContext() const;
+
+ void setPersistentSceneGraph(bool persistent);
+ bool isPersistentSceneGraph() const;
+
QOpenGLContext *openglContext() const;
Q_SIGNALS:
diff --git a/src/quick/items/qquickcanvas_p.h b/src/quick/items/qquickcanvas_p.h
index 147526466e..643d694400 100644
--- a/src/quick/items/qquickcanvas_p.h
+++ b/src/quick/items/qquickcanvas_p.h
@@ -144,7 +144,7 @@ public:
void setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
void clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
- void notifyFocusChangesRecur(QQuickItem **item, int remaining);
+ static void notifyFocusChangesRecur(QQuickItem **item, int remaining);
void updateFocusItemTransform();
@@ -184,6 +184,11 @@ public:
uint clearBeforeRendering : 1;
+ // Currently unused in the default implementation, as we're not stopping
+ // rendering when obscured as we should...
+ uint persistentGLContext : 1;
+ uint persistentSceneGraph : 1;
+
QOpenGLFramebufferObject *renderTarget;
uint renderTargetId;
QSize renderTargetSize;
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index b6d3ebd7f2..62d0e4aa41 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -887,11 +887,11 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
bool stealY = stealMouse;
bool stealX = stealMouse;
- qint64 elapsed = computeCurrentTime(event) - lastPressTime;
+ qint64 elapsedSincePress = computeCurrentTime(event) - lastPressTime;
if (q->yflick()) {
qreal dy = event->localPos().y() - pressPos.y();
- if (qAbs(dy) > qApp->styleHints()->startDragDistance() || elapsed > 200) {
+ if (qAbs(dy) > qApp->styleHints()->startDragDistance() || elapsedSincePress > 200) {
if (!vMoved)
vData.dragStartOffset = dy;
qreal newY = dy + vData.pressPos - vData.dragStartOffset;
@@ -924,7 +924,7 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
if (q->xflick()) {
qreal dx = event->localPos().x() - pressPos.x();
- if (qAbs(dx) > qApp->styleHints()->startDragDistance() || elapsed > 200) {
+ if (qAbs(dx) > qApp->styleHints()->startDragDistance() || elapsedSincePress > 200) {
if (!hMoved)
hData.dragStartOffset = dx;
qreal newX = dx + hData.pressPos - hData.dragStartOffset;
@@ -974,28 +974,26 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
q->movementStarting();
}
- if (!lastPos.isNull()) {
- qint64 currentTimestamp = computeCurrentTime(event);
- qreal elapsed = qreal(currentTimestamp - lastPosTime) / 1000.;
- if (elapsed <= 0)
- return;
- lastPosTime = currentTimestamp;
- QQuickMouseEventEx *extended = QQuickMouseEventEx::extended(event);
- if (q->yflick() && !rejectY) {
- if (extended && extended->capabilities().testFlag(QTouchDevice::Velocity)) {
- vData.addVelocitySample(extended->velocity().y(), maxVelocity);
- } else {
- qreal dy = event->localPos().y()-lastPos.y();
- vData.addVelocitySample(dy/elapsed, maxVelocity);
- }
+ qint64 currentTimestamp = computeCurrentTime(event);
+ qreal elapsed = qreal(currentTimestamp - (lastPos.isNull() ? lastPressTime : lastPosTime)) / 1000.;
+ if (elapsed <= 0)
+ return;
+ lastPosTime = currentTimestamp;
+ QQuickMouseEventEx *extended = QQuickMouseEventEx::extended(event);
+ if (q->yflick() && !rejectY) {
+ if (extended && extended->capabilities().testFlag(QTouchDevice::Velocity)) {
+ vData.addVelocitySample(extended->velocity().y(), maxVelocity);
+ } else {
+ qreal dy = event->localPos().y() - (lastPos.isNull() ? pressPos.y() : lastPos.y());
+ vData.addVelocitySample(dy/elapsed, maxVelocity);
}
- if (q->xflick() && !rejectX) {
- if (extended && extended->capabilities().testFlag(QTouchDevice::Velocity)) {
- hData.addVelocitySample(extended->velocity().x(), maxVelocity);
- } else {
- qreal dx = event->localPos().x()-lastPos.x();
- hData.addVelocitySample(dx/elapsed, maxVelocity);
- }
+ }
+ if (q->xflick() && !rejectX) {
+ if (extended && extended->capabilities().testFlag(QTouchDevice::Velocity)) {
+ hData.addVelocitySample(extended->velocity().x(), maxVelocity);
+ } else {
+ qreal dx = event->localPos().x() - (lastPos.isNull() ? pressPos.x() : lastPos.x());
+ hData.addVelocitySample(dx/elapsed, maxVelocity);
}
}
@@ -1763,6 +1761,10 @@ void QQuickFlickable::mouseUngrabEvent()
d->draggingEnding();
d->stealMouse = false;
setKeepMouseGrab(false);
+ d->fixupX();
+ d->fixupY();
+ if (!d->timeline.isActive())
+ movementEnding();
}
}
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 423fb0f40c..2a744c0559 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -1621,6 +1621,36 @@ void QQuickItemPrivate::setAccessibleFlagAndListener()
}
}
+void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
+{
+ Q_Q(QQuickItem);
+ Q_ASSERT(scope);
+
+ QQuickItemPrivate *scopePrivate = QQuickItemPrivate::get(scope);
+
+ QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
+ // Correct focus chain in scope
+ if (oldSubFocusItem) {
+ QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
+ while (sfi && sfi != scope) {
+ QQuickItemPrivate::get(sfi)->subFocusItem = 0;
+ sfi = sfi->parentItem();
+ }
+ }
+
+ if (focus) {
+ scopePrivate->subFocusItem = q;
+ QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
+ while (sfi && sfi != scope) {
+ QQuickItemPrivate::get(sfi)->subFocusItem = q;
+ sfi = sfi->parentItem();
+ }
+ } else {
+ scopePrivate->subFocusItem = 0;
+ }
+}
+
+
/*!
\class QQuickItem
\brief The QQuickItem class provides the most basic of all visual items in QML.
@@ -1794,10 +1824,13 @@ QQuickItem::~QQuickItem()
Q_D(QQuickItem);
+ if (d->canvasRefCount > 1)
+ d->canvasRefCount = 1; // Make sure canvas is set to null in next call to derefCanvas().
if (d->parentItem)
setParentItem(0);
- else if (d->canvas && d->itemNodeInstance)
- QQuickCanvasPrivate::get(d->canvas)->cleanup(d->itemNodeInstance); // cleanup root
+ else if (d->canvas)
+ d->derefCanvas();
+
// XXX todo - optimize
while (!d->childItems.isEmpty())
d->childItems.first()->setParentItem(0);
@@ -1894,19 +1927,22 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
QQuickItem *scopeItem = 0;
- if (d->canvas && hasFocus()) {
- scopeItem = oldParentItem;
- while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
+ if (hasFocus())
scopeFocusedItem = this;
- } else if (d->canvas && !isFocusScope() && d->subFocusItem) {
- scopeItem = oldParentItem;
- while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
+ else if (!isFocusScope() && d->subFocusItem)
scopeFocusedItem = d->subFocusItem;
- }
- if (scopeFocusedItem)
- QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
+ if (scopeFocusedItem) {
+ scopeItem = oldParentItem;
+ while (!scopeItem->isFocusScope() && scopeItem->parentItem())
+ scopeItem = scopeItem->parentItem();
+ if (d->canvas) {
+ QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
QQuickCanvasPrivate::DontChangeFocusProperty);
+ } else {
+ QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, false);
+ }
+ }
const bool wasVisible = isVisible();
op->removeChild(this);
@@ -1917,35 +1953,54 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
QQuickCanvasPrivate::get(d->canvas)->parentlessItems.remove(this);
}
- d->parentItem = parentItem;
-
- QQuickCanvas *parentCanvas = parentItem?QQuickItemPrivate::get(parentItem)->canvas:0;
- if (d->canvas != parentCanvas) {
- QQuickItemPrivate::InitializationState initState;
- initState.clear();
- d->initCanvas(&initState, parentCanvas);
+ QQuickCanvas *oldParentCanvas = oldParentItem ? QQuickItemPrivate::get(oldParentItem)->canvas : 0;
+ QQuickCanvas *parentCanvas = parentItem ? QQuickItemPrivate::get(parentItem)->canvas : 0;
+ if (oldParentCanvas == parentCanvas) {
+ // Avoid freeing and reallocating resources if the canvas stays the same.
+ d->parentItem = parentItem;
+ } else {
+ if (oldParentCanvas)
+ d->derefCanvas();
+ d->parentItem = parentItem;
+ if (parentCanvas)
+ d->refCanvas(parentCanvas);
}
d->dirty(QQuickItemPrivate::ParentChanged);
if (d->parentItem)
QQuickItemPrivate::get(d->parentItem)->addChild(this);
+ else if (d->canvas)
+ QQuickCanvasPrivate::get(d->canvas)->parentlessItems.insert(this);
d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
d->setEffectiveEnableRecur(0, d->calcEffectiveEnable());
- if (scopeFocusedItem && d->parentItem && d->canvas) {
- // We need to test whether this item becomes scope focused
- QQuickItem *scopeItem = 0;
- scopeItem = d->parentItem;
- while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
+ if (d->parentItem) {
+ if (!scopeFocusedItem) {
+ if (hasFocus())
+ scopeFocusedItem = this;
+ else if (!isFocusScope() && d->subFocusItem)
+ scopeFocusedItem = d->subFocusItem;
+ }
- if (scopeItem->scopedFocusItem()) {
- QQuickItemPrivate::get(scopeFocusedItem)->focus = false;
- emit scopeFocusedItem->focusChanged(false);
- } else {
- QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem,
- QQuickCanvasPrivate::DontChangeFocusProperty);
+ if (scopeFocusedItem) {
+ // We need to test whether this item becomes scope focused
+ QQuickItem *scopeItem = d->parentItem;
+ while (!scopeItem->isFocusScope() && scopeItem->parentItem())
+ scopeItem = scopeItem->parentItem();
+
+ if (scopeItem->scopedFocusItem()) {
+ QQuickItemPrivate::get(scopeFocusedItem)->focus = false;
+ emit scopeFocusedItem->focusChanged(false);
+ } else {
+ if (d->canvas) {
+ QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem,
+ QQuickCanvasPrivate::DontChangeFocusProperty);
+ } else {
+ QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, true);
+ }
+ }
}
}
@@ -2129,30 +2184,82 @@ QQuickItem *QQuickItemPrivate::InitializationState::getFocusScope(QQuickItem *it
return focusScope;
}
-void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
+void QQuickItemPrivate::refCanvas(InitializationState *state, QQuickCanvas *c)
{
- Q_Q(QQuickItem);
+ // An item needs a canvas if it is referenced by another item which has a canvas.
+ // Typically the item is referenced by a parent, but can also be referenced by a
+ // ShaderEffect or ShaderEffectSource. 'canvasRefCount' counts how many items with
+ // a canvas is referencing this item. When the reference count goes from zero to one,
+ // or one to zero, the canvas of this item is updated and propagated to the children.
+ // As long as the reference count stays above zero, the canvas is unchanged.
+ // refCanvas() increments the reference count.
+ // derefCanvas() decrements the reference count.
- if (canvas) {
- removeFromDirtyList();
- QQuickCanvasPrivate *c = QQuickCanvasPrivate::get(canvas);
- if (polishScheduled)
- c->itemsToPolish.remove(q);
- if (c->mouseGrabberItem == q)
- c->mouseGrabberItem = 0;
- if ( hoverEnabled )
- c->hoverItems.removeAll(q);
- if (itemNodeInstance)
- c->cleanup(itemNodeInstance);
- if (!parentItem)
- c->parentlessItems.remove(q);
+ Q_Q(QQuickItem);
+ Q_ASSERT((canvas != 0) == (canvasRefCount > 0));
+ Q_ASSERT(c);
+ if (++canvasRefCount > 1) {
+ if (c != canvas)
+ qWarning("QQuickItem: Cannot use same item on different canvases at the same time.");
+ return; // Canvas already set.
}
+ Q_ASSERT(canvas == 0);
canvas = c;
- if (canvas && polishScheduled)
+ if (polishScheduled)
QQuickCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
+ InitializationState _dummy;
+ InitializationState *childState = state;
+
+ if (q->isFocusScope()) {
+ _dummy.clear(q);
+ childState = &_dummy;
+ }
+
+ if (!parentItem)
+ QQuickCanvasPrivate::get(canvas)->parentlessItems.insert(q);
+
+ for (int ii = 0; ii < childItems.count(); ++ii) {
+ QQuickItem *child = childItems.at(ii);
+ QQuickItemPrivate::get(child)->refCanvas(childState, c);
+ }
+
+ dirty(Canvas);
+
+ if (extra.isAllocated() && extra->screenAttached)
+ extra->screenAttached->canvasChanged(c);
+ itemChange(QQuickItem::ItemSceneChange, c);
+}
+
+void QQuickItemPrivate::derefCanvas()
+{
+ Q_Q(QQuickItem);
+ Q_ASSERT((canvas != 0) == (canvasRefCount > 0));
+
+ if (!canvas)
+ return; // This can happen when destroying recursive shader effect sources.
+
+ if (--canvasRefCount > 0)
+ return; // There are still other references, so don't set canvas to null yet.
+
+ q->releaseResources();
+ removeFromDirtyList();
+ QQuickCanvasPrivate *c = QQuickCanvasPrivate::get(canvas);
+ if (polishScheduled)
+ c->itemsToPolish.remove(q);
+ if (c->mouseGrabberItem == q)
+ c->mouseGrabberItem = 0;
+ if ( hoverEnabled )
+ c->hoverItems.removeAll(q);
+ if (itemNodeInstance)
+ c->cleanup(itemNodeInstance);
+ if (!parentItem)
+ c->parentlessItems.remove(q);
+
+ canvas = 0;
+
itemNodeInstance = 0;
if (extra.isAllocated()) {
@@ -2165,39 +2272,19 @@ void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
groupNode = 0;
paintNode = 0;
- InitializationState _dummy;
- InitializationState *childState = state;
-
- if (c && q->isFocusScope()) {
- _dummy.clear(q);
- childState = &_dummy;
- }
-
- if (!parentItem && canvas)
- QQuickCanvasPrivate::get(canvas)->parentlessItems.insert(q);
-
for (int ii = 0; ii < childItems.count(); ++ii) {
QQuickItem *child = childItems.at(ii);
- QQuickItemPrivate::get(child)->initCanvas(childState, c);
- }
-
- if (c && focus) {
- // Fixup
- if (state->getFocusScope(q)->scopedFocusItem()) {
- focus = false;
- emit q->focusChanged(false);
- } else {
- QQuickCanvasPrivate::get(canvas)->setFocusInScope(state->getFocusScope(q), q);
- }
+ QQuickItemPrivate::get(child)->derefCanvas();
}
dirty(Canvas);
if (extra.isAllocated() && extra->screenAttached)
- extra->screenAttached->canvasChanged(c);
- itemChange(QQuickItem::ItemSceneChange, c);
+ extra->screenAttached->canvasChanged(0);
+ itemChange(QQuickItem::ItemSceneChange, (QQuickCanvas *)0);
}
+
/*!
Returns a transform that maps points from canvas space into item space.
*/
@@ -2300,7 +2387,7 @@ bool QQuickItem::isComponentComplete() const
QQuickItemPrivate::QQuickItemPrivate()
: _anchors(0), _stateGroup(0),
flags(0), widthValid(false), heightValid(false), baselineOffsetValid(false), componentComplete(true),
- keepMouse(false), keepTouch(false), hoverEnabled(false), smooth(false), focus(false), activeFocus(false), notifiedFocus(false),
+ keepMouse(false), keepTouch(false), hoverEnabled(false), smooth(true), focus(false), activeFocus(false), notifiedFocus(false),
notifiedActiveFocus(false), filtersChildMouseEvents(false), explicitVisible(true),
effectiveVisible(true), explicitEnable(true), effectiveEnable(true), polishScheduled(false),
inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true),
@@ -2310,7 +2397,7 @@ QQuickItemPrivate::QQuickItemPrivate()
dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
- canvas(0), parentItem(0), sortedChildItems(&childItems),
+ canvas(0), canvasRefCount(0), parentItem(0), sortedChildItems(&childItems),
subFocusItem(0),
@@ -2954,6 +3041,23 @@ QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
return 0;
}
+/*!
+ This function is called when the item's scene graph resources are no longer needed.
+ It allows items to free its resources, for instance textures, that are not owned by scene graph
+ nodes. Note that scene graph nodes are managed by QQuickCanvas and should not be deleted by
+ this function. Scene graph resources are no longer needed when the parent is set to null and
+ the item is not used by any \l ShaderEffect or \l ShaderEffectSource.
+
+ This function is called from the main thread. Therefore, resources used by the scene graph
+ should not be deleted directly, but by calling \l QObject::deleteLater().
+
+ \note The item destructor still needs to free its scene graph resources if not already done.
+ */
+
+void QQuickItem::releaseResources()
+{
+}
+
QSGTransformNode *QQuickItemPrivate::createTransformNode()
{
return new QSGTransformNode;
@@ -3018,6 +3122,10 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
void QQuickItem::focusInEvent(QFocusEvent *)
{
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessibleEvent ev(this, QAccessible::Focus);
+ QAccessible::updateAccessibility(&ev);
+#endif
}
void QQuickItem::focusOutEvent(QFocusEvent *)
@@ -3988,7 +4096,12 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
childVisibilityChanged |= QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible);
-
+#ifndef QT_NO_ACCESSIBILITY
+ if (isAccessible) {
+ QAccessibleEvent ev(q, effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide);
+ QAccessible::updateAccessibility(&ev);
+ }
+#endif
emit q->visibleChanged();
if (childVisibilityChanged)
emit q->visibleChildrenChanged();
@@ -4217,13 +4330,15 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
/*!
\property QQuickItem::smooth
- \brief whether the item is smoothly transformed.
+ \brief whether the item is smoothed or not.
- This property is provided purely for the purpose of optimization. Turning
- smooth transforms off is faster, but looks worse; turning smooth
- transformations on is slower, but looks better.
+ Primarily used in image based elements to decide if the item should use smooth
+ sampling or not. Smooth sampling is performed using linear interpolation, while
+ non-smooth is performed using nearest neighbor.
- By default smooth transformations are off.
+ In Qt Quick 2.0, this property has minimal impact on performance.
+
+ By default is true.
*/
/*!
@@ -4650,15 +4765,33 @@ void QQuickItem::setFocus(bool focus)
if (d->focus == focus)
return;
- if (d->canvas) {
+ if (d->canvas || d->parentItem) {
// Need to find our nearest focus scope
QQuickItem *scope = parentItem();
- while (scope && !scope->isFocusScope())
+ while (scope && !scope->isFocusScope() && scope->parentItem())
scope = scope->parentItem();
- if (focus)
- QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scope, this);
- else
- QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scope, this);
+ if (d->canvas) {
+ if (focus)
+ QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scope, this);
+ else
+ QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scope, this);
+ } else {
+ // do the focus changes from setFocusInScope/clearFocusInScope that are
+ // unrelated to a canvas
+ QVarLengthArray<QQuickItem *, 20> changed;
+ QQuickItem *oldSubFocusItem = QQuickItemPrivate::get(scope)->subFocusItem;
+ if (oldSubFocusItem) {
+ QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
+ changed << oldSubFocusItem;
+ }
+ d->updateSubFocusItem(scope, focus);
+
+ d->focus = focus;
+ changed << this;
+ emit focusChanged(focus);
+
+ QQuickCanvasPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1);
+ }
} else {
d->focus = focus;
emit focusChanged(focus);
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index f14d60b028..70a8ebc932 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -396,6 +396,7 @@ protected:
const QRectF &oldGeometry);
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ virtual void releaseResources();
virtual void updatePolish();
protected Q_SLOTS:
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 03fc66eadb..01e8b4d335 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -450,6 +450,7 @@ public:
QQuickItem**prevDirtyItem;
QQuickCanvas *canvas;
+ int canvasRefCount;
inline QSGContext *sceneGraphContext() const;
QQuickItem *parentItem;
@@ -472,9 +473,13 @@ public:
private:
QQuickItem *focusScope;
};
- void initCanvas(InitializationState *, QQuickCanvas *);
+
+ void refCanvas(QQuickCanvas *);
+ void refCanvas(InitializationState *, QQuickCanvas *);
+ void derefCanvas();
QQuickItem *subFocusItem;
+ void updateSubFocusItem(QQuickItem *scope, bool focus);
QTransform canvasToItemTransform() const;
QTransform itemToCanvasTransform() const;
@@ -856,6 +861,13 @@ QQuickItem::TransformOrigin QQuickItemPrivate::origin() const
return extra.isAllocated()?extra->origin:QQuickItem::Center;
}
+inline void QQuickItemPrivate::refCanvas(QQuickCanvas *c)
+{
+ QQuickItemPrivate::InitializationState initState;
+ initState.clear();
+ refCanvas(&initState, c);
+}
+
QSGTransformNode *QQuickItemPrivate::itemNode()
{
if (!itemNodeInstance) {
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index a1c398eeb6..3e84eb6115 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -927,6 +927,8 @@ QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actio
void QQuickPathAnimationUpdater::setValue(qreal v)
{
+ v = qMin(qMax(v, (qreal)0.0), (qreal)1.0);;
+
if (interruptStart.isValid()) {
if (reverse)
v = 1 - v;
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 50a3216bf0..0d95500860 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1101,9 +1101,9 @@ void QQuickItemView::trackedPositionChanged()
if (d->layoutOrientation() == Qt::Vertical)
endOffset += d->vData.endMargin;
else if (d->isContentFlowReversed())
- endOffset += d->hData.endMargin;
- else
endOffset += d->hData.startMargin;
+ else
+ endOffset += d->hData.endMargin;
trackedPos += endOffset;
trackedEndPos += endOffset;
toItemPos += endOffset;
@@ -1204,12 +1204,11 @@ qreal QQuickItemView::minXExtent() const
return QQuickFlickable::minXExtent();
if (d->hData.minExtentDirty) {
- d->minExtent = -d->startPosition();
+ d->minExtent = -d->startPosition() + d->hData.startMargin;
qreal highlightStart;
qreal highlightEnd;
qreal endPositionFirstItem = 0;
if (d->isContentFlowReversed()) {
- d->minExtent += d->hData.endMargin;
if (d->model && d->model->count())
endPositionFirstItem = d->positionAt(d->model->count()-1);
else if (d->header)
@@ -1222,7 +1221,6 @@ qreal QQuickItemView::minXExtent() const
if (d->minExtent < maxX)
d->minExtent = maxX;
} else {
- d->minExtent += d->hData.startMargin;
endPositionFirstItem = d->endPositionAt(0);
highlightStart = d->highlightRangeStart;
highlightEnd = d->highlightRangeEnd;
@@ -1279,7 +1277,7 @@ qreal QQuickItemView::maxXExtent() const
if (d->isContentFlowReversed()) {
if (d->header)
d->maxExtent -= d->headerSize();
- d->maxExtent -= d->hData.startMargin;
+ d->maxExtent -= d->hData.endMargin;
} else {
if (d->footer)
d->maxExtent -= d->footerSize();
@@ -1314,7 +1312,7 @@ qreal QQuickItemView::xOrigin() const
{
Q_D(const QQuickItemView);
if (d->isContentFlowReversed())
- return -maxXExtent() + d->size() - d->hData.startMargin;
+ return -maxXExtent() + d->size() - d->hData.endMargin;
else
return -minXExtent() + d->hData.startMargin;
}
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 59cb37c15d..f41ba44943 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -61,6 +61,8 @@ QQuickLoaderPrivate::QQuickLoaderPrivate()
QQuickLoaderPrivate::~QQuickLoaderPrivate()
{
+ delete itemContext;
+ itemContext = 0;
delete incubator;
disposeInitialPropertyValues();
}
@@ -79,12 +81,21 @@ void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRec
void QQuickLoaderPrivate::clear()
{
+ Q_Q(QQuickLoader);
disposeInitialPropertyValues();
if (incubator)
incubator->clear();
+ delete itemContext;
+ itemContext = 0;
+
if (loadingFromSource && component) {
+ // disconnect since we deleteLater
+ QObject::disconnect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
+ q, SLOT(_q_sourceLoaded()));
+ QObject::disconnect(component, SIGNAL(progressChanged(qreal)),
+ q, SIGNAL(progressChanged()));
component->deleteLater();
component = 0;
}
@@ -545,6 +556,7 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
QQml_setParent_noEvent(itemContext, obj);
QQml_setParent_noEvent(item, q);
item->setParentItem(q);
+ itemContext = 0;
}
if (initialPropertyValues.IsEmpty())
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 1fa0a90b28..b85a449c51 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -1422,6 +1422,9 @@ void QQuickPathView::mouseUngrabEvent()
d->stealMouse = false;
setKeepMouseGrab(false);
d->lastPosTime.invalidate();
+ d->fixOffset();
+ if (!d->tl.isActive())
+ movementEnding();
}
}
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index d7eedd42b6..e232746417 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -398,12 +398,27 @@ void QQuickShaderEffect::updateLogAndStatus(const QString &log, int status)
emit statusChanged();
}
+void QQuickShaderEffect::sourceDestroyed(QObject *object)
+{
+ for (int i = 0; i < m_sources.size(); ++i) {
+ SourceData &source = m_sources[i];
+ if (object == source.sourceObject)
+ source.sourceObject = 0;
+ }
+}
+
void QQuickShaderEffect::setSource(const QVariant &var, int index)
{
Q_ASSERT(index >= 0 && index < m_sources.size());
SourceData &source = m_sources[index];
+ if (source.sourceObject) {
+ if (canvas())
+ QQuickItemPrivate::get(source.sourceObject)->derefCanvas();
+ disconnect(source.sourceObject, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
+ }
+
source.sourceObject = 0;
if (var.isNull()) {
return;
@@ -425,16 +440,13 @@ void QQuickShaderEffect::setSource(const QVariant &var, int index)
source.sourceObject = item;
if (item) {
- QQuickItemPrivate *d = QQuickItemPrivate::get(item);
// 'item' needs a canvas to get a scene graph node. It usually gets one through its
// parent, but if the source item is "inline" rather than a reference -- i.e.
// "property variant source: Image { }" instead of "property variant source: foo" -- it
// will not get a parent. In those cases, 'item' should get the canvas from 'this'.
- if (!d->parentItem && canvas() && !d->canvas) {
- QQuickItemPrivate::InitializationState initState;
- initState.clear();
- d->initCanvas(&initState, canvas());
- }
+ if (canvas())
+ QQuickItemPrivate::get(item)->refCanvas(canvas());
+ connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
}
}
@@ -512,6 +524,11 @@ void QQuickShaderEffect::reset()
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
delete source.mapper;
+ if (source.sourceObject) {
+ if (canvas())
+ QQuickItemPrivate::get(source.sourceObject)->derefCanvas();
+ disconnect(source.sourceObject, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
+ }
}
m_sources.clear();
m_log.clear();
@@ -817,15 +834,22 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
}
for (int i = 0; i < oldTextures.size(); ++i) {
QSGTextureProvider *t = oldTextures.at(i).second;
- if (t)
+ if (t) {
disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
+ disconnect(t, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
+ }
}
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
QSGTextureProvider *t = source.sourceObject ? source.sourceObject->textureProvider() : 0;
textures.append(qMakePair(source.name, t));
- if (t)
- connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
+ if (t) {
+ Q_ASSERT_X(t->thread() == QThread::currentThread(),
+ "QQuickShaderEffect::updatePaintNode",
+ "Texture provider must belong to the rendering thread");
+ connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
+ connect(t, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
+ }
}
material->setUniforms(values);
material->setTextureProviders(textures);
@@ -840,12 +864,15 @@ void QQuickShaderEffect::itemChange(ItemChange change, const ItemChangeData &val
{
if (change == QQuickItem::ItemSceneChange) {
// See comment in QQuickShaderEffect::setSource().
- for (int i = 0; i < m_sources.size(); ++i) {
- QQuickItemPrivate *d = QQuickItemPrivate::get(m_sources.at(i).sourceObject);
- if (!d->parentItem && value.canvas != d->canvas) {
- QQuickItemPrivate::InitializationState initState;
- initState.clear();
- d->initCanvas(&initState, value.canvas);
+ if (value.canvas) {
+ for (int i = 0; i < m_sources.size(); ++i) {
+ if (m_sources.at(i).sourceObject)
+ QQuickItemPrivate::get(m_sources.at(i).sourceObject)->refCanvas(value.canvas);
+ }
+ } else {
+ for (int i = 0; i < m_sources.size(); ++i) {
+ if (m_sources.at(i).sourceObject)
+ QQuickItemPrivate::get(m_sources.at(i).sourceObject)->derefCanvas();
}
}
}
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index 4475c22b28..db1e4e78c1 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -133,6 +133,7 @@ private Q_SLOTS:
void updateData();
void updateGeometry();
void updateLogAndStatus(const QString &log, int status);
+ void sourceDestroyed(QObject *object);
private:
friend class QQuickCustomMaterialShader;
@@ -156,7 +157,7 @@ private:
struct SourceData
{
QSignalMapper *mapper;
- QPointer<QQuickItem> sourceObject;
+ QQuickItem *sourceObject;
QByteArray name;
};
QVector<SourceData> m_sources;
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index ae61ad940d..c4b91844e0 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -376,6 +376,14 @@ void QQuickShaderEffectMaterial::updateTextures() const
}
}
+void QQuickShaderEffectMaterial::invalidateTextureProvider(QSGTextureProvider *provider)
+{
+ for (int i = 0; i < m_textures.size(); ++i) {
+ if (provider == m_textures.at(i).second)
+ m_textures[i].second = 0;
+ }
+}
+
QQuickShaderEffectNode::QQuickShaderEffectNode()
: m_material(this)
@@ -397,6 +405,12 @@ void QQuickShaderEffectNode::markDirtyTexture()
markDirty(DirtyMaterial);
}
+void QQuickShaderEffectNode::textureProviderDestroyed(QObject *object)
+{
+ Q_ASSERT(qobject_cast<QSGTextureProvider *>(object));
+ m_material.invalidateTextureProvider(static_cast<QSGTextureProvider *>(object));
+}
+
void QQuickShaderEffectNode::preprocess()
{
Q_ASSERT(material());
diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h
index fc47f626e1..e22d2de9e2 100644
--- a/src/quick/items/qquickshadereffectnode_p.h
+++ b/src/quick/items/qquickshadereffectnode_p.h
@@ -102,6 +102,7 @@ public:
void setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures);
const QVector<QPair<QByteArray, QSGTextureProvider *> > &textureProviders() const;
void updateTextures() const;
+ void invalidateTextureProvider(QSGTextureProvider *provider);
protected:
friend class QQuickCustomMaterialShader;
@@ -143,6 +144,7 @@ Q_SIGNALS:
private Q_SLOTS:
void markDirtyTexture();
+ void textureProviderDestroyed(QObject *object);
private:
QQuickShaderEffectMaterial m_material;
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index 33776be712..c55b1ca7f5 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -54,6 +54,39 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
+namespace
+{
+ class BindableFbo : public QSGBindable
+ {
+ public:
+ BindableFbo(QOpenGLFramebufferObject *fbo, QSGDepthStencilBuffer *depthStencil);
+ virtual ~BindableFbo();
+ virtual void bind() const;
+ private:
+ QOpenGLFramebufferObject *m_fbo;
+ QSGDepthStencilBuffer *m_depthStencil;
+ };
+
+ BindableFbo::BindableFbo(QOpenGLFramebufferObject *fbo, QSGDepthStencilBuffer *depthStencil)
+ : m_fbo(fbo)
+ , m_depthStencil(depthStencil)
+ {
+ }
+
+ BindableFbo::~BindableFbo()
+ {
+ if (m_depthStencil)
+ m_depthStencil->detach();
+ }
+
+ void BindableFbo::bind() const
+ {
+ m_fbo->bind();
+ if (m_depthStencil)
+ m_depthStencil->attach();
+ }
+}
+
class QQuickShaderEffectSourceTextureProvider : public QSGTextureProvider
{
Q_OBJECT
@@ -239,6 +272,7 @@ void QQuickShaderEffectTexture::grab()
delete m_fbo;
delete m_secondaryFbo;
m_fbo = m_secondaryFbo = 0;
+ m_depthStencilBuffer.clear();
m_dirtyTexture = false;
if (m_grab)
emit scheduledUpdateCompleted();
@@ -272,13 +306,12 @@ void QQuickShaderEffectTexture::grab()
delete m_secondaryFbo;
QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setSamples(8);
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
+ m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
} else {
QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setMipmap(m_mipmap);
if (m_recursive) {
@@ -287,6 +320,7 @@ void QQuickShaderEffectTexture::grab()
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
updateBindOptions(true);
+ m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
} else {
delete m_fbo;
delete m_secondaryFbo;
@@ -294,6 +328,7 @@ void QQuickShaderEffectTexture::grab()
m_secondaryFbo = 0;
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
updateBindOptions(true);
+ m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_fbo);
}
}
}
@@ -336,7 +371,7 @@ void QQuickShaderEffectTexture::grab()
m_renderer->setClearColor(Qt::transparent);
if (m_multisampling) {
- m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
+ m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data()));
if (deleteFboLater) {
delete m_fbo;
@@ -354,7 +389,7 @@ void QQuickShaderEffectTexture::grab()
QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
} else {
if (m_recursive) {
- m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
+ m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data()));
if (deleteFboLater) {
delete m_fbo;
@@ -368,7 +403,7 @@ void QQuickShaderEffectTexture::grab()
}
qSwap(m_fbo, m_secondaryFbo);
} else {
- m_renderer->renderScene(QSGBindableFbo(m_fbo));
+ m_renderer->renderScene(BindableFbo(m_fbo, m_depthStencilBuffer.data()));
}
}
@@ -504,6 +539,8 @@ QQuickShaderEffectSource::~QQuickShaderEffectSource()
QQuickItemPrivate *sd = QQuickItemPrivate::get(m_sourceItem);
sd->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
sd->derefFromEffectItem(m_hideSource);
+ if (canvas())
+ sd->derefCanvas();
}
}
@@ -599,6 +636,9 @@ void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
d->derefFromEffectItem(m_hideSource);
d->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ disconnect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*)));
+ if (canvas())
+ d->derefCanvas();
}
m_sourceItem = item;
@@ -608,18 +648,25 @@ void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
// parent, but if the source item is "inline" rather than a reference -- i.e.
// "sourceItem: Item { }" instead of "sourceItem: foo" -- it will not get a parent.
// In those cases, 'item' should get the canvas from 'this'.
- if (!d->parentItem && canvas() && !d->canvas) {
- QQuickItemPrivate::InitializationState initState;
- initState.clear();
- d->initCanvas(&initState, canvas());
- }
+ if (canvas())
+ d->refCanvas(canvas());
d->refFromEffectItem(m_hideSource);
d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ connect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*)));
}
update();
emit sourceItemChanged();
}
+void QQuickShaderEffectSource::sourceItemDestroyed(QObject *item)
+{
+ Q_ASSERT(item == m_sourceItem);
+ m_sourceItem = 0;
+ update();
+ emit sourceItemChanged();
+}
+
+
/*!
\qmlproperty rect ShaderEffectSource::sourceRect
@@ -841,22 +888,35 @@ static void get_wrap_mode(QQuickShaderEffectSource::WrapMode mode, QSGTexture::W
}
+void QQuickShaderEffectSource::releaseResources()
+{
+ if (m_texture) {
+ m_texture->deleteLater();
+ m_texture = 0;
+ }
+ if (m_provider) {
+ m_provider->deleteLater();
+ m_provider = 0;
+ }
+}
+
QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
if (!m_sourceItem || m_sourceItem->width() == 0 || m_sourceItem->height() == 0) {
+ if (m_texture)
+ m_texture->setItem(0);
delete oldNode;
return 0;
}
ensureTexture();
- QQuickShaderEffectTexture *tex = qobject_cast<QQuickShaderEffectTexture *>(m_texture);
- tex->setLive(m_live);
- tex->setItem(QQuickItemPrivate::get(m_sourceItem)->itemNode());
+ m_texture->setLive(m_live);
+ m_texture->setItem(QQuickItemPrivate::get(m_sourceItem)->itemNode());
QRectF sourceRect = m_sourceRect.width() == 0 || m_sourceRect.height() == 0
? QRectF(0, 0, m_sourceItem->width(), m_sourceItem->height())
: m_sourceRect;
- tex->setRect(sourceRect);
+ m_texture->setRect(sourceRect);
QSize textureSize = m_textureSize.isEmpty()
? QSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())))
: m_textureSize;
@@ -869,13 +929,13 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
while (textureSize.height() < minTextureSize.height())
textureSize.rheight() *= 2;
- tex->setSize(textureSize);
- tex->setRecursive(m_recursive);
- tex->setFormat(GLenum(m_format));
- tex->setHasMipmaps(m_mipmap);
+ m_texture->setSize(textureSize);
+ m_texture->setRecursive(m_recursive);
+ m_texture->setFormat(GLenum(m_format));
+ m_texture->setHasMipmaps(m_mipmap);
if (m_grab)
- tex->scheduleUpdate();
+ m_texture->scheduleUpdate();
m_grab = false;
QSGTexture::Filtering filtering = QQuickItemPrivate::get(this)->smooth
@@ -924,12 +984,10 @@ void QQuickShaderEffectSource::itemChange(ItemChange change, const ItemChangeDat
{
if (change == QQuickItem::ItemSceneChange && m_sourceItem) {
// See comment in QQuickShaderEffectSource::setSourceItem().
- QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
- if (!d->parentItem && value.canvas != d->canvas) {
- QQuickItemPrivate::InitializationState initState;
- initState.clear();
- d->initCanvas(&initState, value.canvas);
- }
+ if (value.canvas)
+ QQuickItemPrivate::get(m_sourceItem)->refCanvas(value.canvas);
+ else
+ QQuickItemPrivate::get(m_sourceItem)->derefCanvas();
}
QQuickItem::itemChange(change, value);
}
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 793e89cd69..0853394339 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -136,6 +136,7 @@ private:
QSGRenderer *m_renderer;
QOpenGLFramebufferObject *m_fbo;
QOpenGLFramebufferObject *m_secondaryFbo;
+ QSharedPointer<QSGDepthStencilBuffer> m_depthStencilBuffer;
#ifdef QSG_DEBUG_FBO_OVERLAY
QSGRectangleNode *m_debugOverlay;
@@ -228,7 +229,11 @@ Q_SIGNALS:
void scheduledUpdateCompleted();
+private Q_SLOTS:
+ void sourceItemDestroyed(QObject *item);
+
protected:
+ virtual void releaseResources();
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect);
@@ -240,7 +245,7 @@ private:
QQuickShaderEffectSourceTextureProvider *m_provider;
QQuickShaderEffectTexture *m_texture;
WrapMode m_wrapMode;
- QPointer<QQuickItem> m_sourceItem;
+ QQuickItem *m_sourceItem;
QRectF m_sourceRect;
QSize m_textureSize;
Format m_format;
diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp
index e0535ed77e..724bf8fef1 100644
--- a/src/quick/items/qquicksprite.cpp
+++ b/src/quick/items/qquicksprite.cpp
@@ -248,12 +248,14 @@ int QQuickSprite::variedDuration() const //Deals with precedence when multiple d
+ (m_frameDurationVariation * ((qreal)qrand()/RAND_MAX) * 2)
- m_frameDurationVariation;
return qMax(0, m_frames * mspf);
- }
- qWarning() << "Sprite::duration is changing meaning to the full animation duration.";
- qWarning() << "Use Sprite::frameDuration for the old meaning, of per frame duration.";
- qWarning() << "As an interim measure, duration/durationVariation means the same as frameDuration/frameDurationVariation, and you'll get this warning spewed out everywhere to movtivate you.";
+ } else if (duration() >= 0) {
+ qWarning() << "Sprite::duration is changing meaning to the full animation duration.";
+ qWarning() << "Use Sprite::frameDuration for the old meaning, of per frame duration.";
+ qWarning() << "As an interim measure, duration/durationVariation means the same as frameDuration/frameDurationVariation, and you'll get this warning spewed out everywhere to motivate you.";
//Note that the spammyness is due to this being the best location to detect, but also called once each animation loop
- return QQuickStochasticState::variedDuration() * m_frames;
+ return QQuickStochasticState::variedDuration() * m_frames;
+ }
+ return 1000; //When nothing set
}
void QQuickSprite::startImageLoading()
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index 1c35688c29..d4ddbc400d 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -411,9 +411,9 @@ QImage QQuickSpriteEngine::assembledImage()
int frameWidth = state->m_frameWidth;
int frameHeight = state->m_frameHeight;
if (img.height() == frameHeight && img.width() < maxSize){//Simple case
- p.drawImage(0,y,img);
+ p.drawImage(0,y,img.copy(state->m_frameX,0,state->m_frames * frameWidth, frameHeight));
+ state->m_rowStartX = 0;
state->m_rowY = y;
- state->m_rowStartX = state->m_frameX;//In case it was offset, but we took the simple route of not chopping out the other bits
y += frameHeight;
}else{//Chopping up image case
state->m_framesPerRow = image.width()/frameWidth;
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
index 3763509462..00cefbfbc0 100644
--- a/src/quick/items/qquickspriteengine_p.h
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -70,7 +70,7 @@ class Q_AUTOTEST_EXPORT QQuickStochasticState : public QObject //Currently for i
public:
QQuickStochasticState(QObject* parent = 0)
: QObject(parent)
- , m_duration(1000)
+ , m_duration(-1)
, m_durationVariation(0)
, m_randomStart(false)
{
diff --git a/src/quick/items/qquickspriteimage.cpp b/src/quick/items/qquickspriteimage.cpp
index 6edb3ad8c3..2a151d02a8 100644
--- a/src/quick/items/qquickspriteimage.cpp
+++ b/src/quick/items/qquickspriteimage.cpp
@@ -261,7 +261,7 @@ struct SpriteVertices {
The sprite or sprites to draw. Sprites will be scaled to the size of this element.
*/
-//TODO: Implicitly size element to size of first sprite?
+//TODO: Implicitly size element to size of first sprite? or currentSprite?
QQuickSpriteImage::QQuickSpriteImage(QQuickItem *parent) :
QQuickItem(parent)
, m_node(0)
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 9f22dfdd08..d7303352c5 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -421,6 +421,10 @@ void QQuickTextPrivate::updateSize()
//setup instance of QTextLayout for all cases other than richtext
if (!richText) {
QRectF textRect = setupTextLayout(&naturalWidth);
+
+ if (internalWidthUpdate) // probably the result of a binding loop, but by letting it
+ return; // get this far we'll get a warning to that effect if it is.
+
layedOutTextRect = textRect;
size = textRect.size();
dy -= size.height();
@@ -443,7 +447,13 @@ void QQuickTextPrivate::updateSize()
if (requireImplicitWidth && q->widthValid()) {
extra->doc->setTextWidth(-1);
naturalWidth = extra->doc->idealWidth();
+ const bool wasInLayout = internalWidthUpdate;
+ internalWidthUpdate = true;
+ q->setImplicitWidth(naturalWidth);
+ internalWidthUpdate = wasInLayout;
}
+ if (internalWidthUpdate)
+ return;
if (wrapMode != QQuickText::NoWrap && q->widthValid())
extra->doc->setTextWidth(q->width());
else
@@ -468,8 +478,6 @@ void QQuickTextPrivate::updateSize()
qreal iWidth = -1;
if (!q->widthValid())
iWidth = size.width();
- else if (requireImplicitWidth)
- iWidth = naturalWidth;
if (iWidth > -1)
q->setImplicitSize(iWidth, size.height());
internalWidthUpdate = false;
@@ -697,6 +705,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
layout.endLayout();
*naturalWidth = layout.maximumWidth();
layout.clearLayout();
+
+ bool wasInLayout = internalWidthUpdate;
+ internalWidthUpdate = true;
+ q->setImplicitWidth(*naturalWidth);
+ internalWidthUpdate = wasInLayout;
}
QFontMetrics fm(font);
@@ -704,7 +717,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
return QRect(0, 0, 0, height);
}
- const qreal lineWidth = q->widthValid() ? q->width() : FLT_MAX;
+ qreal lineWidth = q->widthValid() && q->width() > 0 ? q->width() : FLT_MAX;
const qreal maxHeight = q->heightValid() ? q->height() : FLT_MAX;
const bool customLayout = isLineLaidOutConnected();
@@ -735,6 +748,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
QTextLine line;
int visibleCount = 0;
bool elide;
+ bool widthChanged;
qreal height = 0;
QString elideText;
bool once = true;
@@ -755,13 +769,14 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
scaledFont.setPointSize(scaledFontSize);
layout.setFont(scaledFont);
}
- layout.beginLayout();
+ layout.beginLayout();
bool wrapped = false;
bool truncateHeight = false;
truncated = false;
elide = false;
+ widthChanged = false;
int characterCount = 0;
int unwrappedLineCount = 1;
int maxLineCount = maximumLineCount();
@@ -864,7 +879,6 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
br = br.united(line.naturalTextRect());
line = nextLine;
}
-
layout.endLayout();
br.moveTop(0);
@@ -886,8 +900,21 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
if (!line.isValid())
break;
}
+
*naturalWidth = qMax(*naturalWidth, widthLayout.maximumWidth());
}
+
+ bool wasInLayout = internalWidthUpdate;
+ internalWidthUpdate = true;
+ q->setImplicitWidth(*naturalWidth);
+ internalWidthUpdate = wasInLayout;
+
+ const qreal oldWidth = lineWidth;
+ lineWidth = q->widthValid() && q->width() > 0 ? q->width() : FLT_MAX;
+ if (lineWidth != oldWidth && (singlelineElide || multilineElide || canWrap || horizontalFit)) {
+ widthChanged = true;
+ continue;
+ }
}
// If the next needs to be elided and there's an abbreviated string available
@@ -911,32 +938,36 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
if (horizontalFit) {
if (unelidedRect.width() > lineWidth || (!verticalFit && wrapped)) {
largeFont = scaledFontSize - 1;
- scaledFontSize = (smallFont + largeFont) / 2;
if (smallFont > largeFont)
break;
+ scaledFontSize = (smallFont + largeFont) / 2;
+ if (pixelSize)
+ scaledFont.setPixelSize(scaledFontSize);
+ else
+ scaledFont.setPointSize(scaledFontSize);
continue;
} else if (!verticalFit) {
smallFont = scaledFontSize;
- scaledFontSize = (smallFont + largeFont + 1) / 2;
if (smallFont == largeFont)
break;
+ scaledFontSize = (smallFont + largeFont + 1) / 2;
}
}
if (verticalFit) {
if (truncateHeight || unelidedRect.height() > maxHeight) {
largeFont = scaledFontSize - 1;
- scaledFontSize = (smallFont + largeFont + 1) / 2;
if (smallFont > largeFont)
break;
+ scaledFontSize = (smallFont + largeFont) / 2;
+
} else {
smallFont = scaledFontSize;
- scaledFontSize = (smallFont + largeFont + 1) / 2;
if (smallFont == largeFont)
break;
+ scaledFontSize = (smallFont + largeFont + 1) / 2;
}
}
-
}
if (eos != multilengthEos)
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 9a61312910..1846d03b9b 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -531,29 +531,12 @@ void QQuickTextControlPrivate::extendWordwiseSelection(int suggestedNewPosition,
if (!wordSelectionEnabled && (mouseXPosition < wordStartX || mouseXPosition > wordEndX))
return;
- if (wordSelectionEnabled) {
- if (suggestedNewPosition < selectedWordOnDoubleClick.position()) {
- cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
- setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
- } else {
- cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
- setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
- }
+ if (suggestedNewPosition < selectedWordOnDoubleClick.position()) {
+ cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
+ setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
} else {
- // keep the already selected word even when moving to the left
- // (#39164)
- if (suggestedNewPosition < selectedWordOnDoubleClick.position())
- cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
- else
- cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
-
- const qreal differenceToStart = mouseXPosition - wordStartX;
- const qreal differenceToEnd = wordEndX - mouseXPosition;
-
- if (differenceToStart < differenceToEnd)
- setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
- else
- setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
+ cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
+ setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
}
if (interactionFlags & Qt::TextSelectableByMouse) {
@@ -594,13 +577,6 @@ void QQuickTextControlPrivate::extendBlockwiseSelection(int suggestedNewPosition
}
}
-void QQuickTextControlPrivate::_q_deleteSelected()
-{
- if (!(interactionFlags & Qt::TextEditable) || !cursor.hasSelection())
- return;
- cursor.removeSelectedText();
-}
-
void QQuickTextControl::undo()
{
Q_D(QQuickTextControl);
@@ -690,14 +666,6 @@ void QQuickTextControl::paste(QClipboard::Mode mode)
}
#endif
-void QQuickTextControl::clear()
-{
- Q_D(QQuickTextControl);
- // clears and sets empty content
- d->setContent();
-}
-
-
void QQuickTextControl::selectAll()
{
Q_D(QQuickTextControl);
@@ -1527,13 +1495,6 @@ QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property) cons
}
}
-void QQuickTextControl::setFocus(bool focus, Qt::FocusReason reason)
-{
- QFocusEvent ev(focus ? QEvent::FocusIn : QEvent::FocusOut,
- reason);
- processEvent(&ev);
-}
-
void QQuickTextControlPrivate::focusEvent(QFocusEvent *e)
{
Q_Q(QQuickTextControl);
@@ -1555,31 +1516,6 @@ void QQuickTextControlPrivate::focusEvent(QFocusEvent *e)
}
}
-QString QQuickTextControlPrivate::anchorForCursor(const QTextCursor &anchorCursor) const
-{
- if (anchorCursor.hasSelection()) {
- QTextCursor cursor = anchorCursor;
- if (cursor.selectionStart() != cursor.position())
- cursor.setPosition(cursor.selectionStart());
- cursor.movePosition(QTextCursor::NextCharacter);
- QTextCharFormat fmt = cursor.charFormat();
- if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref))
- return fmt.stringProperty(QTextFormat::AnchorHref);
- }
- return QString();
-}
-
-QTextCursor QQuickTextControl::cursorForPosition(const QPointF &pos) const
-{
- Q_D(const QQuickTextControl);
- int cursorPos = hitTest(pos, Qt::FuzzyHit);
- if (cursorPos == -1)
- cursorPos = 0;
- QTextCursor c(d->doc);
- c.setPosition(cursorPos);
- return c;
-}
-
QRectF QQuickTextControl::cursorRect(const QTextCursor &cursor) const
{
Q_D(const QQuickTextControl);
@@ -1609,23 +1545,6 @@ QString QQuickTextControl::anchorAt(const QPointF &pos) const
return d->doc->documentLayout()->anchorAt(pos);
}
-QString QQuickTextControl::anchorAtCursor() const
-{
- Q_D(const QQuickTextControl);
-
- return d->anchorForCursor(d->cursor);
-}
-
-int QQuickTextControl::cursorWidth() const
-{
-#ifndef QT_NO_PROPERTIES
- Q_D(const QQuickTextControl);
- return d->doc->documentLayout()->property("cursorWidth").toInt();
-#else
- return 1;
-#endif
-}
-
void QQuickTextControl::setCursorWidth(int width)
{
Q_D(QQuickTextControl);
@@ -1639,36 +1558,12 @@ void QQuickTextControl::setCursorWidth(int width)
d->repaintCursor();
}
-bool QQuickTextControl::acceptRichText() const
-{
- Q_D(const QQuickTextControl);
- return d->acceptRichText;
-}
-
void QQuickTextControl::setAcceptRichText(bool accept)
{
Q_D(QQuickTextControl);
d->acceptRichText = accept;
}
-void QQuickTextControl::setTextWidth(qreal width)
-{
- Q_D(QQuickTextControl);
- d->doc->setTextWidth(width);
-}
-
-qreal QQuickTextControl::textWidth() const
-{
- Q_D(const QQuickTextControl);
- return d->doc->textWidth();
-}
-
-QSizeF QQuickTextControl::size() const
-{
- Q_D(const QQuickTextControl);
- return d->doc->size();
-}
-
void QQuickTextControl::moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode)
{
Q_D(QQuickTextControl);
@@ -1700,24 +1595,12 @@ void QQuickTextControl::setCursorIsFocusIndicator(bool b)
d->repaintCursor();
}
-bool QQuickTextControl::cursorIsFocusIndicator() const
-{
- Q_D(const QQuickTextControl);
- return d->cursorIsFocusIndicator;
-}
-
void QQuickTextControl::setWordSelectionEnabled(bool enabled)
{
Q_D(QQuickTextControl);
d->wordSelectionEnabled = enabled;
}
-bool QQuickTextControl::isWordSelectionEnabled() const
-{
- Q_D(const QQuickTextControl);
- return d->wordSelectionEnabled;
-}
-
QMimeData *QQuickTextControl::createMimeDataFromSelection() const
{
Q_D(const QQuickTextControl);
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index 97ecdc4c6e..9e3fc90eb1 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -80,12 +80,6 @@ class Q_AUTOTEST_EXPORT QQuickTextControl : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickTextControl)
-#ifndef QT_NO_TEXTHTMLPARSER
- Q_PROPERTY(QString html READ toHtml WRITE setHtml NOTIFY textChanged USER true)
-#endif
- Q_PROPERTY(bool acceptRichText READ acceptRichText WRITE setAcceptRichText)
- Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
- Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
public:
explicit QQuickTextControl(QTextDocument *doc, QObject *parent = 0);
virtual ~QQuickTextControl();
@@ -104,7 +98,6 @@ public:
QString toHtml() const;
#endif
- QTextCursor cursorForPosition(const QPointF &pos) const;
QRectF cursorRect(const QTextCursor &cursor) const;
QRectF cursorRect() const;
QRectF selectionRect(const QTextCursor &cursor) const;
@@ -112,26 +105,15 @@ public:
QString anchorAt(const QPointF &pos) const;
- QString anchorAtCursor() const;
-
- int cursorWidth() const;
void setCursorWidth(int width);
- bool acceptRichText() const;
void setAcceptRichText(bool accept);
- void setTextWidth(qreal width);
- qreal textWidth() const;
- QSizeF size() const;
-
void moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor);
bool canPaste() const;
void setCursorIsFocusIndicator(bool b);
- bool cursorIsFocusIndicator() const;
-
- bool isWordSelectionEnabled() const;
void setWordSelectionEnabled(bool enabled);
virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const;
@@ -151,7 +133,6 @@ public Q_SLOTS:
void undo();
void redo();
- void clear();
void selectAll();
Q_SIGNALS:
@@ -175,9 +156,6 @@ public:
virtual void processEvent(QEvent *e, const QMatrix &matrix);
void processEvent(QEvent *e, const QPointF &coordinateOffset = QPointF());
- // control methods
- void setFocus(bool focus, Qt::FocusReason = Qt::OtherFocusReason);
-
virtual QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
virtual QMimeData *createMimeDataFromSelection() const;
@@ -195,7 +173,6 @@ private:
Q_DISABLE_COPY(QQuickTextControl)
Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentCharFormatAndSelection())
Q_PRIVATE_SLOT(d_func(), void _q_emitCursorPosChanged(const QTextCursor &))
- Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected())
Q_PRIVATE_SLOT(d_func(), void _q_updateBlock(const QTextBlock &))
Q_PRIVATE_SLOT(d_func(), void _q_documentLayoutChanged())
};
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index 44bc00221b..9d776ce46b 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -106,8 +106,6 @@ public:
void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition);
void extendBlockwiseSelection(int suggestedNewPosition);
- void _q_deleteSelected();
-
void _q_setCursorAfterUndoRedo(int undoPosition, int charsAdded, int charsRemoved);
QRectF cursorRectPlusUnicodeDirectionMarkers(const QTextCursor &cursor) const;
@@ -116,8 +114,6 @@ public:
inline QRectF selectionRect() const
{ return selectionRect(this->cursor); }
- QString anchorForCursor(const QTextCursor &anchor) const;
-
void keyPressEvent(QKeyEvent *e);
void mousePressEvent(QMouseEvent *event, const QPointF &pos);
void mouseMoveEvent(QMouseEvent *event, const QPointF &pos);
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 5456d3523a..4fa5233b9a 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1143,7 +1143,8 @@ void QQuickTextEdit::setInputMethodHints(Qt::InputMethodHints hints)
void QQuickTextEdit::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
{
- if (newGeometry.width() != oldGeometry.width())
+ Q_D(QQuickTextEdit);
+ if (newGeometry.width() != oldGeometry.width() && d->wrapMode != NoWrap && !d->inLayout)
updateSize();
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
@@ -1477,6 +1478,7 @@ Handles the given mouse \a event.
void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickTextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
if (d->focusOnPress){
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
@@ -1484,7 +1486,6 @@ void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
openSoftwareInputPanel();
}
- d->control->processEvent(event, QPointF(0, -d->yoff));
if (!event->isAccepted())
QQuickImplicitSizeItem::mousePressEvent(event);
}
@@ -1857,6 +1858,13 @@ void QQuickTextEdit::updateSize()
if (d->requireImplicitWidth) {
d->document->setTextWidth(-1);
naturalWidth = d->document->idealWidth();
+
+ const bool wasInLayout = d->inLayout;
+ d->inLayout = true;
+ setImplicitWidth(naturalWidth);
+ 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());
@@ -1888,11 +1896,11 @@ void QQuickTextEdit::updateSize()
d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug)
// ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
qreal iWidth = -1;
- if (!widthValid())
+ if (!widthValid() && !d->requireImplicitWidth)
iWidth = newWidth;
- else if (d->requireImplicitWidth)
- iWidth = naturalWidth;
+
qreal newHeight = d->document->isEmpty() ? fm.height() : d->document->size().height();
+
if (iWidth > -1)
setImplicitSize(iWidth, newHeight);
else
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index 055b5c7929..f0a35d5266 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -78,7 +78,7 @@ public:
, documentDirty(true), dirty(false), richText(false), cursorVisible(false)
, focusOnPress(true), persistentSelection(false), requireImplicitWidth(false)
, selectByMouse(false), canPaste(false), canPasteValid(false), hAlignImplicit(true)
- , rightToLeftText(false), textCached(false)
+ , rightToLeftText(false), textCached(false), inLayout(false)
{
}
@@ -144,6 +144,7 @@ public:
bool hAlignImplicit:1;
bool rightToLeftText:1;
bool textCached:1;
+ bool inLayout:1;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 0b21d6b169..94856b63ab 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1444,13 +1444,9 @@ void QQuickTextInput::mousePressEvent(QMouseEvent *event)
d->pressPos = event->localPos();
- if (d->focusOnPress) {
- bool hadActiveFocus = hasActiveFocus();
- forceActiveFocus();
- // re-open input panel on press if already focused
- if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly)
- openSoftwareInputPanel();
- }
+ if (d->sendMouseEventToInputContext(event))
+ return;
+
if (d->selectByMouse) {
setKeepMouseGrab(false);
d->selectPressed = true;
@@ -1463,12 +1459,18 @@ void QQuickTextInput::mousePressEvent(QMouseEvent *event)
}
}
- if (d->sendMouseEventToInputContext(event))
- return;
-
bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
int cursor = d->positionAt(event->localPos());
d->moveCursor(cursor, mark);
+
+ if (d->focusOnPress) {
+ bool hadActiveFocus = hasActiveFocus();
+ forceActiveFocus();
+ // re-open input panel on press if already focused
+ if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly)
+ openSoftwareInputPanel();
+ }
+
event->setAccepted(true);
}
@@ -1602,9 +1604,11 @@ void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
{
Q_D(QQuickTextInput);
- if (newGeometry.width() != oldGeometry.width())
- d->updateLayout();
- updateCursorRectangle();
+ if (!d->inLayout) {
+ if (newGeometry.width() != oldGeometry.width() && d->wrapMode != NoWrap)
+ d->updateLayout();
+ updateCursorRectangle();
+ }
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
@@ -1614,14 +1618,19 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor + m_preeditCursor);
const int preeditLength = m_textLayout.preeditAreaText().length();
const qreal width = qMax<qreal>(0, q->width());
- qreal widthUsed = currentLine.isValid() ? currentLine.naturalTextWidth() : 0;
+ qreal cix = 0;
+ qreal widthUsed = 0;
+ if (currentLine.isValid()) {
+ cix = currentLine.cursorToX(m_cursor + preeditLength);
+ const qreal cursorWidth = cix >= 0 ? cix : width - cix;
+ widthUsed = qMax(currentLine.naturalTextWidth(), cursorWidth);
+ }
int previousScroll = hscroll;
if (!autoScroll || widthUsed <= width || m_echoMode == QQuickTextInput::NoEcho) {
hscroll = 0;
} else {
Q_ASSERT(currentLine.isValid());
- qreal cix = currentLine.cursorToX(m_cursor + preeditLength);
if (cix - hscroll >= width) {
// text doesn't fit, cursor is to the right of br (scroll right)
hscroll = cix - width;
@@ -1632,6 +1641,10 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
// text doesn't fit, text document is to the left of br; align
// right
hscroll = widthUsed - width;
+ } else if (width - hscroll > widthUsed) {
+ // text doesn't fit, text document is to the right of br; align
+ // left
+ hscroll = width - widthUsed;
}
if (preeditLength > 0) {
// check to ensure long pre-edit text doesn't push the cursor
@@ -2688,6 +2701,38 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate)
}
}
+qreal QQuickTextInputPrivate::getImplicitWidth() const
+{
+ Q_Q(const QQuickTextInput);
+ if (!requireImplicitWidth) {
+ QQuickTextInputPrivate *d = const_cast<QQuickTextInputPrivate *>(this);
+ d->requireImplicitWidth = true;
+
+ if (q->isComponentComplete()) {
+ // One time cost, only incurred if implicitWidth is first requested after
+ // componentComplete.
+ QTextLayout layout(m_text);
+
+ QTextOption option = m_textLayout.textOption();
+ option.setTextDirection(m_layoutDirection);
+ option.setFlags(QTextOption::IncludeTrailingSpaces);
+ option.setWrapMode(QTextOption::WrapMode(wrapMode));
+ option.setAlignment(Qt::Alignment(q->effectiveHAlign()));
+ layout.setTextOption(option);
+ layout.setFont(font);
+ layout.setPreeditArea(m_textLayout.preeditAreaPosition(), m_textLayout.preeditAreaText());
+ layout.beginLayout();
+
+ QTextLine line = layout.createLine();
+ line.setLineWidth(INT_MAX);
+ d->implicitWidth = qCeil(line.naturalTextWidth());
+
+ layout.endLayout();
+ }
+ }
+ return implicitWidth;
+}
+
void QQuickTextInputPrivate::updateLayout()
{
Q_Q(QQuickTextInput);
@@ -2699,7 +2744,6 @@ void QQuickTextInputPrivate::updateLayout()
QTextOption option = m_textLayout.textOption();
option.setTextDirection(layoutDirection());
- option.setFlags(QTextOption::IncludeTrailingSpaces);
option.setWrapMode(QTextOption::WrapMode(wrapMode));
option.setAlignment(Qt::Alignment(q->effectiveHAlign()));
m_textLayout.setTextOption(option);
@@ -2708,9 +2752,17 @@ void QQuickTextInputPrivate::updateLayout()
boundingRect = QRectF();
m_textLayout.beginLayout();
QTextLine line = m_textLayout.createLine();
+ if (requireImplicitWidth) {
+ line.setLineWidth(INT_MAX);
+ const bool wasInLayout = inLayout;
+ inLayout = true;
+ q->setImplicitWidth(qCeil(line.naturalTextWidth()));
+ 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 height = 0;
- QTextLine firstLine = line;
do {
line.setLineWidth(lineWidth);
line.setPosition(QPointF(line.position().x(), height));
@@ -2728,7 +2780,11 @@ void QQuickTextInputPrivate::updateLayout()
updateType = UpdatePaintNode;
q->update();
- q->setImplicitSize(boundingRect.width(), boundingRect.height());
+
+ if (!requireImplicitWidth && !q->widthValid())
+ q->setImplicitSize(qCeil(boundingRect.width()), qCeil(boundingRect.height()));
+ else
+ q->setImplicitHeight(qCeil(boundingRect.height()));
if (previousRect != boundingRect)
emit q->contentSizeChanged();
@@ -3261,7 +3317,14 @@ void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool e
m_textDirty = (oldText != m_text);
bool changed = finishChange(-1, true, edited);
+#ifdef QT_NO_ACCESSIBILITY
Q_UNUSED(changed)
+#else
+ if (changed) {
+ QAccessibleTextUpdateEvent ev(q, 0, oldText, m_text);
+ QAccessible::updateAccessibility(&ev);
+ }
+#endif
}
@@ -3885,6 +3948,11 @@ bool QQuickTextInputPrivate::emitCursorPositionChanged()
}
}
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessibleTextCursorEvent ev(q, m_cursor);
+ QAccessible::updateAccessibility(&ev);
+#endif
+
return true;
}
return false;
@@ -3964,12 +4032,10 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
}
#ifndef QT_NO_SHORTCUT
else if (event == QKeySequence::Undo) {
- if (!m_readOnly)
- q->undo();
+ q->undo();
}
else if (event == QKeySequence::Redo) {
- if (!m_readOnly)
- q->redo();
+ q->redo();
}
else if (event == QKeySequence::SelectAll) {
selectAll();
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index bb00600661..165155acd0 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -125,6 +125,8 @@ public:
, m_acceptableInput(1)
, m_blinkStatus(0)
, m_passwordEchoEditing(false)
+ , inLayout(false)
+ , requireImplicitWidth(false)
{
}
@@ -256,7 +258,8 @@ public:
bool m_acceptableInput : 1;
bool m_blinkStatus : 1;
bool m_passwordEchoEditing : 1;
-
+ bool inLayout:1;
+ bool requireImplicitWidth:1;
static inline QQuickTextInputPrivate *get(QQuickTextInput *t) {
return t->d_func();
@@ -404,6 +407,8 @@ public:
void updateLayout();
+ qreal getImplicitWidth() const;
+
private:
void removeSelectedText();
void internalSetText(const QString &txt, int pos = -1, bool edited = true);
diff --git a/src/quick/items/qquickvisualadaptormodel.cpp b/src/quick/items/qquickvisualadaptormodel.cpp
index 622adf4ce9..cd9db7235b 100644
--- a/src/quick/items/qquickvisualadaptormodel.cpp
+++ b/src/quick/items/qquickvisualadaptormodel.cpp
@@ -65,7 +65,8 @@ public:
}
VDMDelegateDataType(const VDMDelegateDataType &type)
- : metaObject(0)
+ : QQmlRefCount()
+ , metaObject(0)
, propertyCache(0)
, propertyOffset(type.propertyOffset)
, signalOffset(type.signalOffset)
diff --git a/src/quick/items/qquickwindowmanager.cpp b/src/quick/items/qquickwindowmanager.cpp
index 64eb2bf53b..61c2ef24b4 100644
--- a/src/quick/items/qquickwindowmanager.cpp
+++ b/src/quick/items/qquickwindowmanager.cpp
@@ -228,7 +228,7 @@ public slots:
private:
void handleAddedWindows();
void handleAddedWindow(QQuickCanvas *canvas);
- void handleRemovedWindows();
+ void handleRemovedWindows(bool clearGLContext = true);
QSGContext *sg;
QOpenGLContext *gl;
@@ -475,7 +475,7 @@ void QQuickRenderThreadSingleContextWindowManager::hide(QQuickCanvas *canvas)
/*!
Called on Render Thread
*/
-void QQuickRenderThreadSingleContextWindowManager::handleRemovedWindows()
+void QQuickRenderThreadSingleContextWindowManager::handleRemovedWindows(bool clearGLContext)
{
#ifdef THREAD_DEBUG
printf(" RenderThread: about to remove %d\n", m_removed_windows.size());
@@ -496,7 +496,7 @@ void QQuickRenderThreadSingleContextWindowManager::handleRemovedWindows()
// If a window is removed because it has been hidden it will take with it
// the gl context (at least on Mac) if bound, so disconnect the gl context
// from anything
- if (removedAnything)
+ if (removedAnything && clearGLContext)
gl->doneCurrent();
}
@@ -755,7 +755,7 @@ void QQuickRenderThreadSingleContextWindowManager::run()
#endif
m_removed_windows << m_rendered_windows.keys();
- handleRemovedWindows();
+ handleRemovedWindows(false);
sg->invalidate();
diff --git a/src/quick/particles/qquickangledirection.cpp b/src/quick/particles/qquickangledirection.cpp
index a3bd45e0bf..e77c47362c 100644
--- a/src/quick/particles/qquickangledirection.cpp
+++ b/src/quick/particles/qquickangledirection.cpp
@@ -42,6 +42,9 @@
#include "qquickangledirection_p.h"
#include <stdlib.h>
#include <cmath>
+#ifdef Q_OS_QNX
+#include <math.h>
+#endif
QT_BEGIN_NAMESPACE
const qreal CONV = 0.017453292519943295;
/*!
diff --git a/src/quick/particles/qquickcustomparticle.cpp b/src/quick/particles/qquickcustomparticle.cpp
index a8f146ad05..8f75672e32 100644
--- a/src/quick/particles/qquickcustomparticle.cpp
+++ b/src/quick/particles/qquickcustomparticle.cpp
@@ -139,6 +139,12 @@ QQuickCustomParticle::QQuickCustomParticle(QQuickItem* parent)
class QQuickShaderEffectMaterialObject : public QObject, public QQuickShaderEffectMaterial { };
+void QQuickCustomParticle::sceneGraphInvalidated()
+{
+ m_nodes.clear();
+ m_rootNode = 0;
+}
+
QQuickCustomParticle::~QQuickCustomParticle()
{
if (m_material)
diff --git a/src/quick/particles/qquickcustomparticle_p.h b/src/quick/particles/qquickcustomparticle_p.h
index 29f3d19657..e04ac704d0 100644
--- a/src/quick/particles/qquickcustomparticle_p.h
+++ b/src/quick/particles/qquickcustomparticle_p.h
@@ -93,6 +93,8 @@ protected:
QQuickShaderEffectNode *buildCustomNodes();
void performPendingResize();
+ void sceneGraphInvalidated();
+
private:
void buildData();
diff --git a/src/quick/particles/qquickellipseextruder.cpp b/src/quick/particles/qquickellipseextruder.cpp
index 3eb547fd2f..083564e5cb 100644
--- a/src/quick/particles/qquickellipseextruder.cpp
+++ b/src/quick/particles/qquickellipseextruder.cpp
@@ -42,6 +42,11 @@
#include "qquickellipseextruder_p.h"
#include <stdlib.h>
#include <cmath>
+
+#ifdef Q_OS_QNX
+#include <math.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
\qmlclass EllipseShape QQuickEllipseExtruder
diff --git a/src/quick/particles/qquickimageparticle.cpp b/src/quick/particles/qquickimageparticle.cpp
index 386892a12a..d9eb6ed01b 100644
--- a/src/quick/particles/qquickimageparticle.cpp
+++ b/src/quick/particles/qquickimageparticle.cpp
@@ -839,6 +839,13 @@ QQmlListProperty<QQuickSprite> QQuickImageParticle::sprites()
return QQmlListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
}
+void QQuickImageParticle::sceneGraphInvalidated()
+{
+ m_nodes.clear();
+ m_rootNode = 0;
+ m_material = 0;
+}
+
void QQuickImageParticle::setImage(const QUrl &image)
{
if (image.isEmpty()){
diff --git a/src/quick/particles/qquickimageparticle_p.h b/src/quick/particles/qquickimageparticle_p.h
index dca524bcab..4db2c9801a 100644
--- a/src/quick/particles/qquickimageparticle_p.h
+++ b/src/quick/particles/qquickimageparticle_p.h
@@ -348,6 +348,8 @@ protected:
void prepareNextFrame();
void buildParticleNodes();
+ void sceneGraphInvalidated();
+
private slots:
void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
diff --git a/src/quick/particles/qquickparticleemitter.cpp b/src/quick/particles/qquickparticleemitter.cpp
index 0f7f3817f2..035d66cbcd 100644
--- a/src/quick/particles/qquickparticleemitter.cpp
+++ b/src/quick/particles/qquickparticleemitter.cpp
@@ -284,23 +284,17 @@ QQuickParticleExtruder* QQuickParticleEmitter::effectiveExtruder()
void QQuickParticleEmitter::pulse(int milliseconds)
{
- if (!particleCount())
- qWarning() << "pulse called on an emitter with a particle count of zero";
if (!m_enabled)
m_pulseLeft = milliseconds;
}
void QQuickParticleEmitter::burst(int num)
{
- if (!particleCount())
- qWarning() << "burst called on an emitter with a particle count of zero";
m_burstQueue << qMakePair(num, QPointF(x(), y()));
}
void QQuickParticleEmitter::burst(int num, qreal x, qreal y)
{
- if (!particleCount())
- qWarning() << "burst called on an emitter with a particle count of zero";
m_burstQueue << qMakePair(num, QPointF(x, y));
}
diff --git a/src/quick/particles/qquickparticlepainter.cpp b/src/quick/particles/qquickparticlepainter.cpp
index f46f2f2235..e490b70240 100644
--- a/src/quick/particles/qquickparticlepainter.cpp
+++ b/src/quick/particles/qquickparticlepainter.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qquickparticlepainter_p.h"
+#include <QQuickCanvas>
#include <QDebug>
QT_BEGIN_NAMESPACE
/*!
@@ -65,10 +66,22 @@ QT_BEGIN_NAMESPACE
*/
QQuickParticlePainter::QQuickParticlePainter(QQuickItem *parent) :
QQuickItem(parent),
- m_system(0), m_count(0), m_pleaseReset(true)
+ m_system(0), m_count(0), m_pleaseReset(true), m_canvas(0)
{
}
+void QQuickParticlePainter::itemChange(ItemChange change, const ItemChangeData &data)
+{
+ if (change == QQuickItem::ItemSceneChange) {
+ if (m_canvas)
+ disconnect(m_canvas, SIGNAL(sceneGraphInvalidated()), this, SLOT(sceneGraphInvalidated()));
+ m_canvas = data.canvas;
+ if (m_canvas)
+ connect(m_canvas, SIGNAL(sceneGraphInvalidated()), this, SLOT(sceneGraphInvalidated()), Qt::DirectConnection);
+
+ }
+}
+
void QQuickParticlePainter::componentComplete()
{
if (!m_system && qobject_cast<QQuickParticleSystem*>(parentItem()))
diff --git a/src/quick/particles/qquickparticlepainter_p.h b/src/quick/particles/qquickparticlepainter_p.h
index ebe76d98ea..1ae4625856 100644
--- a/src/quick/particles/qquickparticlepainter_p.h
+++ b/src/quick/particles/qquickparticlepainter_p.h
@@ -76,6 +76,8 @@ public:
return m_groups;
}
+ void itemChange(ItemChange, const ItemChangeData &);
+
signals:
void countChanged();
void systemChanged(QQuickParticleSystem* arg);
@@ -96,6 +98,9 @@ public slots:
void calcSystemOffset(bool resetPending = false);
+private slots:
+ virtual void sceneGraphInvalidated() {}
+
protected:
/* Reset resets all your internal data structures. But anything attached to a particle should
be in attached data. So reset + reloads should have no visible effect.
@@ -121,6 +126,8 @@ protected:
QStringList m_groups;
QPointF m_systemOffset;
+ QQuickCanvas *m_canvas;
+
private:
QSet<QPair<int,int> > m_pendingCommits;
};
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index dbac95acd1..cf39c308e7 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
@@ -46,6 +46,10 @@
#include <qopenglfunctions.h>
#include <private/qopenglextensions_p.h>
+#ifdef Q_OS_QNX
+#include <malloc.h>
+#endif
+
QT_BEGIN_NAMESPACE
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 9608ebe861..c78e243dcd 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -45,31 +45,28 @@
#include <QtQuick/private/qsgdistancefieldutil_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
#include <private/qrawfont_p.h>
-#include <private/qdistancefield_p.h>
#include <QtGui/qguiapplication.h>
#include <qdir.h>
QT_BEGIN_NAMESPACE
-QHash<QString, QOpenGLMultiGroupSharedResource> QSGDistanceFieldGlyphCache::m_caches_data;
+QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture;
QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
: ctx(c)
, m_manager(man)
+ , m_pendingGlyphs(64)
{
Q_ASSERT(font.isValid());
- m_font = font;
- m_cacheData = cacheData();
-
- QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
+ QRawFontPrivate *fontD = QRawFontPrivate::get(font);
m_glyphCount = fontD->fontEngine->glyphCount();
- m_cacheData->doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
+ m_doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
- m_referenceFont = m_font;
- m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_cacheData->doubleGlyphResolution));
+ m_referenceFont = font;
+ m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution));
Q_ASSERT(m_referenceFont.isValid());
}
@@ -77,58 +74,31 @@ QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
{
}
-QSGDistanceFieldGlyphCache::GlyphCacheData *QSGDistanceFieldGlyphCache::cacheData()
-{
- QString key = QString::fromLatin1("%1_%2_%3_%4")
- .arg(m_font.familyName())
- .arg(m_font.styleName())
- .arg(m_font.weight())
- .arg(m_font.style());
- return m_caches_data[key].value<QSGDistanceFieldGlyphCache::GlyphCacheData>(ctx);
-}
-
-qreal QSGDistanceFieldGlyphCache::fontScale() const
+QSGDistanceFieldGlyphCache::GlyphData &QSGDistanceFieldGlyphCache::glyphData(glyph_t glyph)
{
- return qreal(m_font.pixelSize()) / QT_DISTANCEFIELD_BASEFONTSIZE(m_cacheData->doubleGlyphResolution);
-}
-
-int QSGDistanceFieldGlyphCache::distanceFieldRadius() const
-{
- return QT_DISTANCEFIELD_DEFAULT_RADIUS / QT_DISTANCEFIELD_SCALE(m_cacheData->doubleGlyphResolution);
-}
-
-QSGDistanceFieldGlyphCache::Metrics QSGDistanceFieldGlyphCache::glyphMetrics(glyph_t glyph)
-{
- QHash<glyph_t, Metrics>::iterator metric = m_metrics.find(glyph);
- if (metric == m_metrics.end()) {
- QPainterPath path = m_font.pathForGlyph(glyph);
- QRectF br = path.boundingRect();
-
- Metrics m;
- m.width = br.width();
- m.height = br.height();
- m.baselineX = br.x();
- m.baselineY = -br.y();
-
- metric = m_metrics.insert(glyph, m);
+ QHash<glyph_t, GlyphData>::iterator data = m_glyphsData.find(glyph);
+ if (data == m_glyphsData.end()) {
+ GlyphData gd;
+ gd.texture = &s_emptyTexture;
+ QPainterPath path = m_referenceFont.pathForGlyph(glyph);
+ gd.boundingRect = path.boundingRect();
+ data = m_glyphsData.insert(glyph, gd);
}
-
- return metric.value();
+ return data.value();
}
-QSGDistanceFieldGlyphCache::TexCoord QSGDistanceFieldGlyphCache::glyphTexCoord(glyph_t glyph) const
+QSGDistanceFieldGlyphCache::Metrics QSGDistanceFieldGlyphCache::glyphMetrics(glyph_t glyph, qreal pixelSize)
{
- return m_cacheData->texCoords.value(glyph);
-}
+ GlyphData &gd = glyphData(glyph);
+ qreal scale = fontScale(pixelSize);
-static QSGDistanceFieldGlyphCache::Texture g_emptyTexture;
+ Metrics m;
+ m.width = gd.boundingRect.width() * scale;
+ m.height = gd.boundingRect.height() * scale;
+ m.baselineX = gd.boundingRect.x() * scale;
+ m.baselineY = -gd.boundingRect.y() * scale;
-const QSGDistanceFieldGlyphCache::Texture *QSGDistanceFieldGlyphCache::glyphTexture(glyph_t glyph) const
-{
- QHash<glyph_t, Texture*>::const_iterator it = m_cacheData->glyphTextures.find(glyph);
- if (it == m_cacheData->glyphTextures.constEnd())
- return &g_emptyTexture;
- return it.value();
+ return m;
}
void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
@@ -143,23 +113,18 @@ void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
continue;
}
- ++m_cacheData->glyphRefCount[glyphIndex];
+ GlyphData &gd = glyphData(glyphIndex);
+ ++gd.ref;
referencedGlyphs.insert(glyphIndex);
- if (m_cacheData->texCoords.contains(glyphIndex) || newGlyphs.contains(glyphIndex))
+ if (gd.texCoord.isValid() || newGlyphs.contains(glyphIndex))
continue;
- QPainterPath path = m_referenceFont.pathForGlyph(glyphIndex);
- m_cacheData->glyphPaths.insert(glyphIndex, path);
- if (path.isEmpty()) {
- TexCoord c;
- c.width = 0;
- c.height = 0;
- m_cacheData->texCoords.insert(glyphIndex, c);
- continue;
- }
+ gd.texCoord.width = 0;
+ gd.texCoord.height = 0;
- newGlyphs.insert(glyphIndex);
+ if (!gd.boundingRect.isEmpty())
+ newGlyphs.insert(glyphIndex);
}
if (newGlyphs.isEmpty())
@@ -175,7 +140,8 @@ void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
int count = glyphs.count();
for (int i = 0; i < count; ++i) {
glyph_t glyphIndex = glyphs.at(i);
- if (--m_cacheData->glyphRefCount[glyphIndex] == 0 && !glyphTexCoord(glyphIndex).isNull())
+ GlyphData &gd = glyphData(glyphIndex);
+ if (--gd.ref == 0 && !gd.texCoord.isNull())
unusedGlyphs.insert(glyphIndex);
}
releaseGlyphs(unusedGlyphs);
@@ -183,7 +149,7 @@ void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
void QSGDistanceFieldGlyphCache::update()
{
- if (m_cacheData->pendingGlyphs.isEmpty())
+ if (m_pendingGlyphs.isEmpty())
return;
QHash<glyph_t, QImage> distanceFields;
@@ -194,16 +160,16 @@ void QSGDistanceFieldGlyphCache::update()
QString tmpPath = QString::fromLatin1("%1/.qt/").arg(QDir::tempPath());
QString keyBase = QString::fromLatin1("%1%2%3_%4_%5_%6.fontblob")
.arg(tmpPath)
- .arg(m_font.familyName())
- .arg(m_font.styleName())
- .arg(m_font.weight())
- .arg(m_font.style());
+ .arg(m_referenceFont.familyName())
+ .arg(m_referenceFont.styleName())
+ .arg(m_referenceFont.weight())
+ .arg(m_referenceFont.style());
if (cacheDistanceFields && !QFile::exists(tmpPath))
QDir(tmpPath).mkpath(tmpPath);
- for (int i = 0; i < m_cacheData->pendingGlyphs.size(); ++i) {
- glyph_t glyphIndex = m_cacheData->pendingGlyphs.at(i);
+ for (int i = 0; i < m_pendingGlyphs.size(); ++i) {
+ glyph_t glyphIndex = m_pendingGlyphs.at(i);
if (cacheDistanceFields) {
QString key = keyBase.arg(glyphIndex);
@@ -219,7 +185,7 @@ void QSGDistanceFieldGlyphCache::update()
}
}
- QImage distanceField = qt_renderDistanceFieldGlyph(m_font, glyphIndex, m_cacheData->doubleGlyphResolution);
+ QImage distanceField = qt_renderDistanceFieldGlyph(m_referenceFont, glyphIndex, m_doubleGlyphResolution);
distanceFields.insert(glyphIndex, distanceField);
if (cacheDistanceFields) {
@@ -230,7 +196,7 @@ void QSGDistanceFieldGlyphCache::update()
}
}
- m_cacheData->pendingGlyphs.reset();
+ m_pendingGlyphs.reset();
storeGlyphs(distanceFields);
}
@@ -242,28 +208,22 @@ void QSGDistanceFieldGlyphCache::setGlyphsPosition(const QList<GlyphPosition> &g
int count = glyphs.count();
for (int i = 0; i < count; ++i) {
GlyphPosition glyph = glyphs.at(i);
+ GlyphData &gd = glyphData(glyph.glyph);
- Q_ASSERT(m_cacheData->glyphPaths.contains(glyph.glyph));
-
- QPainterPath path = m_cacheData->glyphPaths.value(glyph.glyph);
- QRectF br = path.boundingRect();
- TexCoord c;
- c.xMargin = QT_DISTANCEFIELD_RADIUS(m_cacheData->doubleGlyphResolution) / qreal(QT_DISTANCEFIELD_SCALE(m_cacheData->doubleGlyphResolution));
- c.yMargin = QT_DISTANCEFIELD_RADIUS(m_cacheData->doubleGlyphResolution) / qreal(QT_DISTANCEFIELD_SCALE(m_cacheData->doubleGlyphResolution));
- c.x = glyph.position.x();
- c.y = glyph.position.y();
- c.width = br.width();
- c.height = br.height();
-
- if (m_cacheData->texCoords.contains(glyph.glyph))
+ if (!gd.texCoord.isNull())
invalidatedGlyphs.append(glyph.glyph);
- m_cacheData->texCoords.insert(glyph.glyph, c);
+ gd.texCoord.xMargin = QT_DISTANCEFIELD_RADIUS(m_doubleGlyphResolution) / qreal(QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution));
+ gd.texCoord.yMargin = QT_DISTANCEFIELD_RADIUS(m_doubleGlyphResolution) / qreal(QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution));
+ gd.texCoord.x = glyph.position.x();
+ gd.texCoord.y = glyph.position.y();
+ gd.texCoord.width = gd.boundingRect.width();
+ gd.texCoord.height = gd.boundingRect.height();
}
if (!invalidatedGlyphs.isEmpty()) {
- QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
- while (it != m_cacheData->m_registeredNodes.end()) {
+ QLinkedList<QSGDistanceFieldGlyphConsumer *>::iterator it = m_registeredNodes.begin();
+ while (it != m_registeredNodes.end()) {
(*it)->invalidateGlyphs(invalidatedGlyphs);
++it;
}
@@ -287,28 +247,29 @@ void QSGDistanceFieldGlyphCache::processPendingGlyphs()
void QSGDistanceFieldGlyphCache::setGlyphsTexture(const QVector<glyph_t> &glyphs, const Texture &tex)
{
- int i = m_cacheData->textures.indexOf(tex);
+ int i = m_textures.indexOf(tex);
if (i == -1) {
- m_cacheData->textures.append(tex);
- i = m_cacheData->textures.size() - 1;
+ m_textures.append(tex);
+ i = m_textures.size() - 1;
} else {
- m_cacheData->textures[i].size = tex.size;
+ m_textures[i].size = tex.size;
}
- Texture *texture = &(m_cacheData->textures[i]);
+ Texture *texture = &(m_textures[i]);
QVector<quint32> invalidatedGlyphs;
int count = glyphs.count();
for (int j = 0; j < count; ++j) {
glyph_t glyphIndex = glyphs.at(j);
- if (m_cacheData->glyphTextures.contains(glyphIndex))
+ GlyphData &gd = glyphData(glyphIndex);
+ if (gd.texture != &s_emptyTexture)
invalidatedGlyphs.append(glyphIndex);
- m_cacheData->glyphTextures.insert(glyphIndex, texture);
+ gd.texture = texture;
}
if (!invalidatedGlyphs.isEmpty()) {
- QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
- while (it != m_cacheData->m_registeredNodes.end()) {
+ QLinkedList<QSGDistanceFieldGlyphConsumer*>::iterator it = m_registeredNodes.begin();
+ while (it != m_registeredNodes.end()) {
(*it)->invalidateGlyphs(invalidatedGlyphs);
++it;
}
@@ -319,20 +280,14 @@ void QSGDistanceFieldGlyphCache::markGlyphsToRender(const QVector<glyph_t> &glyp
{
int count = glyphs.count();
for (int i = 0; i < count; ++i)
- m_cacheData->pendingGlyphs.add(glyphs.at(i));
-}
-
-void QSGDistanceFieldGlyphCache::removeGlyph(glyph_t glyph)
-{
- m_cacheData->texCoords.remove(glyph);
- m_cacheData->glyphTextures.remove(glyph);
+ m_pendingGlyphs.add(glyphs.at(i));
}
void QSGDistanceFieldGlyphCache::updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize)
{
- int count = m_cacheData->textures.count();
+ int count = m_textures.count();
for (int i = 0; i < count; ++i) {
- Texture &tex = m_cacheData->textures[i];
+ Texture &tex = m_textures[i];
if (tex.textureId == oldTex) {
tex.textureId = newTex;
tex.size = newTexSize;
@@ -341,20 +296,4 @@ void QSGDistanceFieldGlyphCache::updateTexture(GLuint oldTex, GLuint newTex, con
}
}
-bool QSGDistanceFieldGlyphCache::containsGlyph(glyph_t glyph) const
-{
- return m_cacheData->texCoords.contains(glyph);
-}
-
-void QSGDistanceFieldGlyphCache::registerGlyphNode(QSGDistanceFieldGlyphNode *node)
-{
- m_cacheData->m_registeredNodes.append(node);
-}
-
-void QSGDistanceFieldGlyphCache::unregisterGlyphNode(QSGDistanceFieldGlyphNode *node)
-{
- m_cacheData->m_registeredNodes.removeOne(node);
-}
-
-
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 47dfdb4d8c..77cd814ce8 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -54,6 +54,7 @@
#include <private/qfontengine_p.h>
#include <QtGui/private/qdatabuffer_p.h>
#include <private/qopenglcontext_p.h>
+#include <private/qdistancefield_p.h>
// ### remove
#include <QtQuick/private/qquicktext_p.h>
@@ -133,6 +134,14 @@ protected:
QQuickItem *m_ownerElement;
};
+class Q_QUICK_EXPORT QSGDistanceFieldGlyphConsumer
+{
+public:
+ virtual ~QSGDistanceFieldGlyphConsumer() {}
+
+ virtual void invalidateGlyphs(const QVector<quint32> &glyphs) = 0;
+};
+
class Q_QUICK_EXPORT QSGDistanceFieldGlyphCache
{
public:
@@ -172,24 +181,30 @@ public:
const QSGDistanceFieldGlyphCacheManager *manager() const { return m_manager; }
- const QRawFont &font() const { return m_font; }
+ const QRawFont &referenceFont() const { return m_referenceFont; }
- qreal fontScale() const;
- int distanceFieldRadius() const;
+ qreal fontScale(qreal pixelSize) const
+ {
+ return pixelSize / QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution);
+ }
+ int distanceFieldRadius() const
+ {
+ return QT_DISTANCEFIELD_DEFAULT_RADIUS / QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution);
+ }
int glyphCount() const { return m_glyphCount; }
- bool doubleGlyphResolution() const { return m_cacheData->doubleGlyphResolution; }
+ bool doubleGlyphResolution() const { return m_doubleGlyphResolution; }
- Metrics glyphMetrics(glyph_t glyph);
- TexCoord glyphTexCoord(glyph_t glyph) const;
- const Texture *glyphTexture(glyph_t glyph) const;
+ Metrics glyphMetrics(glyph_t glyph, qreal pixelSize);
+ inline TexCoord glyphTexCoord(glyph_t glyph);
+ inline const Texture *glyphTexture(glyph_t glyph);
void populate(const QVector<glyph_t> &glyphs);
void release(const QVector<glyph_t> &glyphs);
void update();
- void registerGlyphNode(QSGDistanceFieldGlyphNode *node);
- void unregisterGlyphNode(QSGDistanceFieldGlyphNode *node);
+ void registerGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.append(node); }
+ void unregisterGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.removeOne(node); }
virtual void registerOwnerElement(QQuickItem *ownerElement);
virtual void unregisterOwnerElement(QQuickItem *ownerElement);
@@ -209,57 +224,64 @@ protected:
void setGlyphsPosition(const QList<GlyphPosition> &glyphs);
void setGlyphsTexture(const QVector<glyph_t> &glyphs, const Texture &tex);
void markGlyphsToRender(const QVector<glyph_t> &glyphs);
- void removeGlyph(glyph_t glyph);
+ inline void removeGlyph(glyph_t glyph);
void updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize);
- bool containsGlyph(glyph_t glyph) const;
+ inline bool containsGlyph(glyph_t glyph);
GLuint textureIdForGlyph(glyph_t glyph) const;
QOpenGLContext *ctx;
private:
- struct GlyphCacheData : public QOpenGLSharedResource {
- QList<Texture> textures;
- QHash<glyph_t, Texture*> glyphTextures;
- QHash<glyph_t, TexCoord> texCoords;
- QDataBuffer<glyph_t> pendingGlyphs;
- QHash<glyph_t, QPainterPath> glyphPaths;
- bool doubleGlyphResolution;
- QLinkedList<QSGDistanceFieldGlyphNode*> m_registeredNodes;
- QHash<glyph_t, quint32> glyphRefCount;
-
- GlyphCacheData(QOpenGLContext *ctx)
- : QOpenGLSharedResource(ctx->shareGroup())
- , pendingGlyphs(64)
- , doubleGlyphResolution(false)
- {}
-
- void invalidateResource()
- {
- textures.clear();
- glyphTextures.clear();
- texCoords.clear();
- }
-
- void freeResource(QOpenGLContext *)
- {
- }
+ struct GlyphData {
+ Texture *texture;
+ TexCoord texCoord;
+ QRectF boundingRect;
+ quint32 ref;
+
+ GlyphData() : texture(0), ref(0) { }
};
+ GlyphData &glyphData(glyph_t glyph);
+
QSGDistanceFieldGlyphCacheManager *m_manager;
- QRawFont m_font;
QRawFont m_referenceFont;
-
int m_glyphCount;
- QHash<glyph_t, Metrics> m_metrics;
- GlyphCacheData *cacheData();
- GlyphCacheData *m_cacheData;
- static QHash<QString, QOpenGLMultiGroupSharedResource> m_caches_data;
+ bool m_doubleGlyphResolution;
+
+ QList<Texture> m_textures;
+ QHash<glyph_t, GlyphData> m_glyphsData;
+ QDataBuffer<glyph_t> m_pendingGlyphs;
+ QLinkedList<QSGDistanceFieldGlyphConsumer*> m_registeredNodes;
+
+ static Texture s_emptyTexture;
};
+inline QSGDistanceFieldGlyphCache::TexCoord QSGDistanceFieldGlyphCache::glyphTexCoord(glyph_t glyph)
+{
+ return glyphData(glyph).texCoord;
+}
+
+inline const QSGDistanceFieldGlyphCache::Texture *QSGDistanceFieldGlyphCache::glyphTexture(glyph_t glyph)
+{
+ return glyphData(glyph).texture;
+}
+
+inline void QSGDistanceFieldGlyphCache::removeGlyph(glyph_t glyph)
+{
+ GlyphData &gd = glyphData(glyph);
+ gd.texCoord = TexCoord();
+ gd.texture = &s_emptyTexture;
+}
+
+inline bool QSGDistanceFieldGlyphCache::containsGlyph(glyph_t glyph)
+{
+ return glyphData(glyph).texCoord.isValid();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 02fbaa1a7f..da1c8e6ee9 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -54,6 +54,7 @@
#include <QGuiApplication>
#include <QOpenGLContext>
+#include <QtGui/qopenglframebufferobject.h>
#include <private/qqmlglobal_p.h>
@@ -95,7 +96,13 @@ class QSGContextPrivate : public QObjectPrivate
public:
QSGContextPrivate()
: gl(0)
+ , depthStencilBufferManager(0)
, distanceFieldCacheManager(0)
+ #ifndef QT_OPENGL_ES
+ , distanceFieldAntialiasing(QSGGlyphNode::HighQualitySubPixelAntialiasing)
+ #else
+ , distanceFieldAntialiasing(QSGGlyphNode::GrayAntialiasing)
+ #endif
, flashMode(qmlFlashMode())
, distanceFieldDisabled(qmlDisableDistanceField())
{
@@ -111,9 +118,11 @@ public:
QHash<QSGMaterialType *, QSGMaterialShader *> materials;
QMutex textureMutex;
QHash<QQuickTextureFactory *, QSGTexture *> textures;
-
+ QSGDepthStencilBufferManager *depthStencilBufferManager;
QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
+ QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing;
+
bool flashMode;
float renderAlpha;
bool distanceFieldDisabled;
@@ -141,6 +150,17 @@ public:
QSGContext::QSGContext(QObject *parent) :
QObject(*(new QSGContextPrivate), parent)
{
+ Q_D(QSGContext);
+ // ### Do something with these before final release...
+ static bool doSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing"));
+ static bool doLowQualSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing-lowq"));
+ static bool doGray = qApp->arguments().contains(QLatin1String("--text-gray-antialiasing"));
+ if (doSubpixel)
+ d->distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing;
+ else if (doLowQualSubpixel)
+ d->distanceFieldAntialiasing = QSGGlyphNode::LowQualitySubPixelAntialiasing;
+ else if (doGray)
+ d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
}
@@ -160,6 +180,8 @@ void QSGContext::invalidate()
d->textureMutex.unlock();
qDeleteAll(d->materials.values());
d->materials.clear();
+ delete d->depthStencilBufferManager;
+ d->depthStencilBufferManager = 0;
delete d->distanceFieldCacheManager;
d->distanceFieldCacheManager = 0;
@@ -270,39 +292,47 @@ QSGImageNode *QSGContext::createImageNode()
/*!
Factory function for scene graph backends of the distance-field glyph cache.
*/
-QSGDistanceFieldGlyphCache *QSGContext::createDistanceFieldGlyphCache(const QRawFont &font)
+QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont &font)
{
Q_D(QSGContext);
- 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);
-
- return new QSGSharedDistanceFieldGlyphCache(keyName,
- sharedGraphicsCache,
- d->distanceFieldCacheManager,
- glContext(),
- font);
+ if (!d->distanceFieldCacheManager)
+ d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager;
+
+ QSGDistanceFieldGlyphCache *cache = d->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,
+ d->distanceFieldCacheManager,
+ glContext(),
+ font);
+ }
}
}
+ if (!cache)
+ cache = new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
+ d->distanceFieldCacheManager->insertCache(font, cache);
}
-
- return new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
+ return cache;
}
/*!
@@ -312,25 +342,11 @@ QSGGlyphNode *QSGContext::createGlyphNode()
{
Q_D(QSGContext);
- // ### Do something with these before final release...
- static bool doSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing"));
- static bool doLowQualSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing-lowq"));
- static bool doGray = qApp->arguments().contains(QLatin1String("--text-gray-antialiasing"));
-
if (d->distanceFieldDisabled) {
return new QSGDefaultGlyphNode;
} else {
- if (!d->distanceFieldCacheManager) {
- d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager(this);
- if (doSubpixel)
- d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::HighQualitySubPixelAntialiasing);
- else if (doLowQualSubpixel)
- d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::LowQualitySubPixelAntialiasing);
- else if (doGray)
- d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::GrayAntialiasing);
- }
-
- QSGGlyphNode *node = new QSGDistanceFieldGlyphNode(d->distanceFieldCacheManager);
+ QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(this);
+ node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing);
return node;
}
}
@@ -399,6 +415,42 @@ QSize QSGContext::minimumFBOSize() const
/*!
+ Returns a shared pointer to a depth stencil buffer that can be used with \a fbo.
+ */
+QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo)
+{
+ Q_D(QSGContext);
+ if (!d->gl)
+ return QSharedPointer<QSGDepthStencilBuffer>();
+ QSGDepthStencilBufferManager *manager = depthStencilBufferManager();
+ QSGDepthStencilBuffer::Format format;
+ format.size = fbo->size();
+ format.samples = fbo->format().samples();
+ format.attachments = QSGDepthStencilBuffer::DepthAttachment | QSGDepthStencilBuffer::StencilAttachment;
+ QSharedPointer<QSGDepthStencilBuffer> buffer = manager->bufferForFormat(format);
+ if (buffer.isNull()) {
+ buffer = QSharedPointer<QSGDepthStencilBuffer>(new QSGDefaultDepthStencilBuffer(d->gl, format));
+ manager->insertBuffer(buffer);
+ }
+ return buffer;
+}
+
+/*!
+ Returns a pointer to the context's depth/stencil buffer manager. This is useful for custom
+ implementations of \l depthStencilBufferForFbo().
+ */
+QSGDepthStencilBufferManager *QSGContext::depthStencilBufferManager()
+{
+ Q_D(QSGContext);
+ if (!d->gl)
+ return 0;
+ if (!d->depthStencilBufferManager)
+ d->depthStencilBufferManager = new QSGDepthStencilBufferManager(d->gl);
+ return d->depthStencilBufferManager;
+}
+
+
+/*!
Returns a material shader for the given material.
*/
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index dfb960f420..7cbff40a9b 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -51,6 +51,7 @@
#include <private/qrawfont_p.h>
#include <QtQuick/qsgnode.h>
+#include <QtQuick/private/qsgdepthstencilbuffer_p.h>
QT_BEGIN_HEADER
@@ -95,7 +96,7 @@ public:
virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId);
- virtual QSGDistanceFieldGlyphCache *createDistanceFieldGlyphCache(const QRawFont &font);
+ virtual QSGDistanceFieldGlyphCache *distanceFieldGlyphCache(const QRawFont &font);
virtual QSGRectangleNode *createRectangleNode();
virtual QSGImageNode *createImageNode();
@@ -104,6 +105,8 @@ public:
virtual QSGTexture *createTexture(const QImage &image = QImage()) const;
virtual QSize minimumFBOSize() const;
+ virtual QSharedPointer<QSGDepthStencilBuffer> depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo);
+ QSGDepthStencilBufferManager *depthStencilBufferManager();
virtual QSurfaceFormat defaultSurfaceFormat() const;
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 5864f35060..2b2ccfe317 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -47,24 +47,41 @@
QT_BEGIN_NAMESPACE
-QHash<QString, QOpenGLMultiGroupSharedResource> QSGDefaultDistanceFieldGlyphCache::m_textures_data;
-
-QSGDefaultDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDefaultDistanceFieldGlyphCache::textureData(QOpenGLContext *c)
-{
- QString key = QString::fromLatin1("%1_%2_%3_%4")
- .arg(font().familyName())
- .arg(font().styleName())
- .arg(font().weight())
- .arg(font().style());
- return m_textures_data[key].value<QSGDefaultDistanceFieldGlyphCache::DistanceFieldTextureData>(c);
-}
QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
: QSGDistanceFieldGlyphCache(man, c, font)
, m_maxTextureSize(0)
, m_maxTextureCount(3)
+ , m_fbo(0)
+ , m_blitProgram(0)
+{
+ m_currentTexture = createTextureInfo();
+
+ m_blitVertexCoordinateArray[0] = -1.0f;
+ m_blitVertexCoordinateArray[1] = -1.0f;
+ m_blitVertexCoordinateArray[2] = 1.0f;
+ m_blitVertexCoordinateArray[3] = -1.0f;
+ m_blitVertexCoordinateArray[4] = 1.0f;
+ m_blitVertexCoordinateArray[5] = 1.0f;
+ m_blitVertexCoordinateArray[6] = -1.0f;
+ m_blitVertexCoordinateArray[7] = 1.0f;
+
+ m_blitTextureCoordinateArray[0] = 0.0f;
+ m_blitTextureCoordinateArray[1] = 0.0f;
+ m_blitTextureCoordinateArray[2] = 1.0f;
+ m_blitTextureCoordinateArray[3] = 0.0f;
+ m_blitTextureCoordinateArray[4] = 1.0f;
+ m_blitTextureCoordinateArray[5] = 1.0f;
+ m_blitTextureCoordinateArray[6] = 0.0f;
+ m_blitTextureCoordinateArray[7] = 1.0f;
+}
+
+QSGDefaultDistanceFieldGlyphCache::~QSGDefaultDistanceFieldGlyphCache()
{
- m_textureData = textureData(c);
+ for (int i = 0; i < m_textures.count(); ++i)
+ glDeleteTextures(1, &m_textures[i].texture);
+ ctx->functions()->glDeleteFramebuffers(1, &m_fbo);
+ delete m_blitProgram;
}
void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
@@ -75,15 +92,15 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
for (QSet<glyph_t>::const_iterator it = glyphs.constBegin(); it != glyphs.constEnd() ; ++it) {
glyph_t glyphIndex = *it;
- if (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty())
+ if (cacheIsFull() && m_unusedGlyphs.isEmpty())
continue;
- if (textureIsFull(m_textureData->currentTexture) && m_textureData->textures.count() < m_maxTextureCount)
- m_textureData->currentTexture = m_textureData->addTexture();
+ if (textureIsFull(m_currentTexture) && m_textures.count() < m_maxTextureCount)
+ m_currentTexture = createTextureInfo();
- m_textureData->unusedGlyphs.remove(glyphIndex);
+ m_unusedGlyphs.remove(glyphIndex);
- DistanceFieldTextureData::TextureInfo *tex = m_textureData->currentTexture;
+ TextureInfo *tex = m_currentTexture;
GlyphPosition p;
p.glyph = glyphIndex;
@@ -97,13 +114,13 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
}
} else {
// Recycle glyphs
- if (!m_textureData->unusedGlyphs.isEmpty()) {
- glyph_t unusedGlyph = *m_textureData->unusedGlyphs.constBegin();
+ if (!m_unusedGlyphs.isEmpty()) {
+ glyph_t unusedGlyph = *m_unusedGlyphs.constBegin();
TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
- tex = m_textureData->glyphsTexture.value(unusedGlyph);
+ tex = m_glyphsTexture.value(unusedGlyph);
p.position = QPointF(unusedCoord.x, unusedCoord.y);
- m_textureData->unusedGlyphs.remove(unusedGlyph);
- m_textureData->glyphsTexture.remove(unusedGlyph);
+ m_unusedGlyphs.remove(unusedGlyph);
+ m_glyphsTexture.remove(unusedGlyph);
removeGlyph(unusedGlyph);
}
}
@@ -111,7 +128,7 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
if (p.position.y() < maxTextureSize()) {
glyphPositions.append(p);
glyphsToRender.append(glyphIndex);
- m_textureData->glyphsTexture.insert(glyphIndex, tex);
+ m_glyphsTexture.insert(glyphIndex, tex);
}
}
@@ -124,13 +141,13 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
int requiredWidth = maxTextureSize();
int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())); // Enough rows to fill the latin1 set by default..
- QHash<DistanceFieldTextureData::TextureInfo *, QVector<glyph_t> > glyphTextures;
+ QHash<TextureInfo *, QVector<glyph_t> > glyphTextures;
QHash<glyph_t, QImage>::const_iterator it;
for (it = glyphs.constBegin(); it != glyphs.constEnd(); ++it) {
glyph_t glyphIndex = it.key();
TexCoord c = glyphTexCoord(glyphIndex);
- DistanceFieldTextureData::TextureInfo *texInfo = m_textureData->glyphsTexture.value(glyphIndex);
+ TextureInfo *texInfo = m_glyphsTexture.value(glyphIndex);
int requiredHeight = qMin(maxTextureSize(),
qMax(texInfo->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()),
@@ -156,7 +173,7 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
}
- QHash<DistanceFieldTextureData::TextureInfo *, QVector<glyph_t> >::const_iterator i;
+ QHash<TextureInfo *, QVector<glyph_t> >::const_iterator i;
for (i = glyphTextures.constBegin(); i != glyphTextures.constEnd(); ++i) {
Texture t;
t.textureId = i.key()->texture;
@@ -167,15 +184,15 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
void QSGDefaultDistanceFieldGlyphCache::referenceGlyphs(const QSet<glyph_t> &glyphs)
{
- m_textureData->unusedGlyphs -= glyphs;
+ m_unusedGlyphs -= glyphs;
}
void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs)
{
- m_textureData->unusedGlyphs += glyphs;
+ m_unusedGlyphs += glyphs;
}
-void QSGDefaultDistanceFieldGlyphCache::createTexture(DistanceFieldTextureData::TextureInfo *texInfo, int width, int height)
+void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int width, int height)
{
if (useWorkaroundBrokenFBOReadback() && texInfo->image.isNull())
texInfo->image = QImage(width, height, QImage::Format_Indexed8);
@@ -202,7 +219,7 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(DistanceFieldTextureData::
}
-void QSGDefaultDistanceFieldGlyphCache::resizeTexture(DistanceFieldTextureData::TextureInfo *texInfo, int width, int height)
+void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int width, int height)
{
int oldWidth = texInfo->size.width();
int oldHeight = texInfo->size.height();
@@ -224,14 +241,14 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(DistanceFieldTextureData::
return;
}
- if (!m_textureData->blitProgram)
- m_textureData->createBlitProgram();
+ if (!m_blitProgram)
+ createBlitProgram();
- Q_ASSERT(m_textureData->blitProgram);
+ Q_ASSERT(m_blitProgram);
- if (!m_textureData->fbo)
- ctx->functions()->glGenFramebuffers(1, &m_textureData->fbo);
- ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_textureData->fbo);
+ if (!m_fbo)
+ ctx->functions()->glGenFramebuffers(1, &m_fbo);
+ ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLuint tmp_texture;
glGenTextures(1, &tmp_texture);
@@ -270,14 +287,14 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(DistanceFieldTextureData::
glViewport(0, 0, oldWidth, oldHeight);
- ctx->functions()->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureData->blitVertexCoordinateArray);
- ctx->functions()->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureData->blitTextureCoordinateArray);
+ ctx->functions()->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_blitVertexCoordinateArray);
+ ctx->functions()->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_blitTextureCoordinateArray);
- m_textureData->blitProgram->bind();
- m_textureData->blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
- m_textureData->blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
- m_textureData->blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR));
- m_textureData->blitProgram->setUniformValue("imageTexture", GLuint(0));
+ m_blitProgram->bind();
+ m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
+ m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+ m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR));
+ m_blitProgram->setUniformValue("imageTexture", GLuint(0));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -304,8 +321,8 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(DistanceFieldTextureData::
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
ctx->functions()->glUseProgram(oldProgram);
- m_textureData->blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
- m_textureData->blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+ m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
+ m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
}
bool QSGDefaultDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index 12bbcce060..38cc649b3a 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -53,6 +53,7 @@ class Q_QUICK_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceField
{
public:
QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
+ virtual ~QSGDefaultDistanceFieldGlyphCache();
void requestGlyphs(const QSet<glyph_t> &glyphs);
void storeGlyphs(const QHash<glyph_t, QImage> &glyphs);
@@ -60,8 +61,8 @@ public:
void releaseGlyphs(const QSet<glyph_t> &glyphs);
bool cacheIsFull() const {
- return m_textureData->textures.count() == m_maxTextureCount
- && textureIsFull(m_textureData->currentTexture);
+ return m_textures.count() == m_maxTextureCount
+ && textureIsFull(m_currentTexture);
}
bool useWorkaroundBrokenFBOReadback() const;
int maxTextureSize() const;
@@ -70,123 +71,67 @@ public:
int maxTextureCount() const { return m_maxTextureCount; }
private:
- mutable int m_maxTextureSize;
- int m_maxTextureCount;
+ struct TextureInfo {
+ GLuint texture;
+ QSize size;
+ int currX;
+ int currY;
+ QImage image;
+
+ TextureInfo() : texture(0), currX(0), currY(0)
+ { }
+ };
- struct DistanceFieldTextureData : public QOpenGLSharedResource {
- struct TextureInfo {
- GLuint texture;
- QSize size;
- int currX;
- int currY;
- QImage image;
-
- TextureInfo() : texture(0), currX(0), currY(0)
- { }
- };
-
- TextureInfo *currentTexture;
- QList<TextureInfo> textures;
- QHash<glyph_t, TextureInfo *> glyphsTexture;
- GLuint fbo;
- QSet<glyph_t> unusedGlyphs;
-
- QOpenGLShaderProgram *blitProgram;
- GLfloat blitVertexCoordinateArray[8];
- GLfloat blitTextureCoordinateArray[8];
-
- TextureInfo *addTexture()
- {
- textures.append(TextureInfo());
- return &textures.last();
- }
+ void createTexture(TextureInfo * texInfo, int width, int height);
+ void resizeTexture(TextureInfo * texInfo, int width, int height);
+ bool textureIsFull (const TextureInfo *tex) const { return tex->currY >= maxTextureSize(); }
- DistanceFieldTextureData(QOpenGLContext *ctx)
- : QOpenGLSharedResource(ctx->shareGroup())
- , fbo(0)
- , blitProgram(0)
- {
- currentTexture = addTexture();
-
- blitVertexCoordinateArray[0] = -1.0f;
- blitVertexCoordinateArray[1] = -1.0f;
- blitVertexCoordinateArray[2] = 1.0f;
- blitVertexCoordinateArray[3] = -1.0f;
- blitVertexCoordinateArray[4] = 1.0f;
- blitVertexCoordinateArray[5] = 1.0f;
- blitVertexCoordinateArray[6] = -1.0f;
- blitVertexCoordinateArray[7] = 1.0f;
-
- blitTextureCoordinateArray[0] = 0.0f;
- blitTextureCoordinateArray[1] = 0.0f;
- blitTextureCoordinateArray[2] = 1.0f;
- blitTextureCoordinateArray[3] = 0.0f;
- blitTextureCoordinateArray[4] = 1.0f;
- blitTextureCoordinateArray[5] = 1.0f;
- blitTextureCoordinateArray[6] = 0.0f;
- blitTextureCoordinateArray[7] = 1.0f;
- }
+ TextureInfo *createTextureInfo()
+ {
+ m_textures.append(TextureInfo());
+ return &m_textures.last();
+ }
- void invalidateResource()
+ void createBlitProgram()
+ {
+ m_blitProgram = new QOpenGLShaderProgram;
{
- glyphsTexture.clear();
- textures.clear();
- fbo = 0;
- delete blitProgram;
- blitProgram = 0;
+ QString source;
+ source.append(QLatin1String(qopenglslMainWithTexCoordsVertexShader));
+ source.append(QLatin1String(qopenglslUntransformedPositionVertexShader));
- currentTexture = addTexture();
- }
+ QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram);
+ vertexShader->compileSourceCode(source);
- void freeResource(QOpenGLContext *ctx)
- {
- glyphsTexture.clear();
- for (int i = 0; i < textures.count(); ++i)
- glDeleteTextures(1, &textures[i].texture);
- textures.clear();
- ctx->functions()->glDeleteFramebuffers(1, &fbo);
- delete blitProgram;
- blitProgram = 0;
-
- currentTexture = addTexture();
+ m_blitProgram->addShader(vertexShader);
}
-
- void createBlitProgram()
{
- blitProgram = new QOpenGLShaderProgram;
- {
- QString source;
- source.append(QLatin1String(qopenglslMainWithTexCoordsVertexShader));
- source.append(QLatin1String(qopenglslUntransformedPositionVertexShader));
-
- QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, blitProgram);
- vertexShader->compileSourceCode(source);
-
- blitProgram->addShader(vertexShader);
- }
- {
- QString source;
- source.append(QLatin1String(qopenglslMainFragmentShader));
- source.append(QLatin1String(qopenglslImageSrcFragmentShader));
-
- QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, blitProgram);
- fragmentShader->compileSourceCode(source);
-
- blitProgram->addShader(fragmentShader);
- }
- blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
- blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
- blitProgram->link();
+ QString source;
+ source.append(QLatin1String(qopenglslMainFragmentShader));
+ source.append(QLatin1String(qopenglslImageSrcFragmentShader));
+
+ QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram);
+ fragmentShader->compileSourceCode(source);
+
+ m_blitProgram->addShader(fragmentShader);
}
- };
+ m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+ m_blitProgram->link();
+ }
+
+ mutable int m_maxTextureSize;
+ int m_maxTextureCount;
- void createTexture(DistanceFieldTextureData::TextureInfo * texInfo, int width, int height);
- void resizeTexture(DistanceFieldTextureData::TextureInfo * texInfo, int width, int height);
- bool textureIsFull (const DistanceFieldTextureData::TextureInfo *tex) const { return tex->currY >= maxTextureSize(); }
+ TextureInfo *m_currentTexture;
+ QList<TextureInfo> m_textures;
+ QHash<glyph_t, TextureInfo *> m_glyphsTexture;
+ GLuint m_fbo;
+ QSet<glyph_t> m_unusedGlyphs;
- DistanceFieldTextureData *textureData(QOpenGLContext *c);
- DistanceFieldTextureData *m_textureData;
- static QHash<QString, QOpenGLMultiGroupSharedResource> m_textures_data;
+ QOpenGLShaderProgram *m_blitProgram;
+ GLfloat m_blitVertexCoordinateArray[8];
+ GLfloat m_blitTextureCoordinateArray[8];
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index a86e663755..d6fe6f938c 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -46,9 +46,10 @@
QT_BEGIN_NAMESPACE
-QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager)
- : m_material(0)
- , m_glyph_cacheManager(cacheManager)
+QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGContext *context)
+ : m_glyphNodeType(RootGlyphNode)
+ , m_context(context)
+ , m_material(0)
, m_glyph_cache(0)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
, m_style(QQuickText::Normal)
@@ -59,7 +60,6 @@ QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheM
{
m_geometry.setDrawingMode(GL_TRIANGLES);
setGeometry(&m_geometry);
- setPreferredAntialiasingMode(cacheManager->defaultAntialiasingMode());
setFlag(UsePreprocess);
#ifdef QML_RUNTIME_TESTING
description = QLatin1String("glyphs");
@@ -70,15 +70,17 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
{
delete m_material;
+ if (m_glyphNodeType == SubGlyphNode)
+ return;
+
if (m_glyph_cache) {
m_glyph_cache->release(m_glyphs.glyphIndexes());
m_glyph_cache->unregisterGlyphNode(this);
m_glyph_cache->unregisterOwnerElement(ownerElement());
}
- for (int i = 0; i < m_nodesToDelete.count(); ++i)
- delete m_nodesToDelete.at(i);
- m_nodesToDelete.clear();
+ while (m_nodesToDelete.count())
+ delete m_nodesToDelete.takeLast();
}
void QSGDistanceFieldGlyphNode::setColor(const QColor &color)
@@ -107,8 +109,15 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
m_position = QPointF(position.x(), position.y() - font.ascent());
m_glyphs = glyphs;
+ m_dirtyGeometry = true;
+ m_dirtyMaterial = true;
+
QSGDistanceFieldGlyphCache *oldCache = m_glyph_cache;
- m_glyph_cache = m_glyph_cacheManager->cache(m_glyphs.rawFont());
+ m_glyph_cache = m_context->distanceFieldGlyphCache(m_glyphs.rawFont());
+
+ if (m_glyphNodeType == SubGlyphNode)
+ return;
+
if (m_glyph_cache != oldCache) {
Q_ASSERT(ownerElement() != 0);
if (oldCache) {
@@ -123,9 +132,6 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
const QVector<quint32> glyphIndexes = m_glyphs.glyphIndexes();
for (int i = 0; i < glyphIndexes.count(); ++i)
m_allGlyphIndexesLookup.insert(glyphIndexes.at(i));
-
- m_dirtyGeometry = true;
- m_dirtyMaterial = true;
}
void QSGDistanceFieldGlyphNode::setStyle(QQuickText::TextStyle style)
@@ -154,9 +160,8 @@ void QSGDistanceFieldGlyphNode::preprocess()
{
Q_ASSERT(m_glyph_cache);
- for (int i = 0; i < m_nodesToDelete.count(); ++i)
- delete m_nodesToDelete.at(i);
- m_nodesToDelete.clear();
+ while (m_nodesToDelete.count())
+ delete m_nodesToDelete.takeLast();
m_glyph_cache->processPendingGlyphs();
m_glyph_cache->update();
@@ -183,14 +188,15 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
Q_ASSERT(m_glyph_cache);
// Remove previously created sub glyph nodes
- QHash<const QSGDistanceFieldGlyphCache::Texture *, QSGDistanceFieldGlyphNode *>::iterator it = m_subNodes.begin();
- while (it != m_subNodes.end()) {
- removeChildNode(it.value());
+ // We assume all the children are sub glyph nodes
+ QSGNode *subnode = firstChild();
+ while (subnode) {
// We can't delete the node now as it might be in the preprocess list
// It will be deleted in the next preprocess
- m_nodesToDelete.append(it.value());
- it = m_subNodes.erase(it);
+ m_nodesToDelete.append(subnode);
+ subnode = subnode->nextSibling();
}
+ removeAllChildNodes();
QSGGeometry *g = geometry();
@@ -200,6 +206,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
const QVector<quint32> indexes = m_glyphs.glyphIndexes();
const QVector<QPointF> positions = m_glyphs.positions();
+ qreal fontPixelSize = m_glyphs.rawFont().pixelSize();
QVector<QSGGeometry::TexturedPoint2D> vp;
vp.reserve(indexes.size() * 4);
@@ -207,8 +214,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
ip.reserve(indexes.size() * 6);
QPointF margins(2, 2);
- QPointF texMargins = margins / m_glyph_cache->fontScale();
-
+ QPointF texMargins = margins / m_glyph_cache->fontScale(fontPixelSize);
for (int i = 0; i < indexes.size(); ++i) {
const int glyphIndex = indexes.at(i);
@@ -232,7 +238,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
continue;
}
- QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
+ QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex, fontPixelSize);
if (!metrics.isNull() && !c.isNull()) {
metrics.width += margins.x() * 2;
@@ -288,25 +294,19 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo>::const_iterator ite = glyphsInOtherTextures.constBegin();
while (ite != glyphsInOtherTextures.constEnd()) {
- QHash<const QSGDistanceFieldGlyphCache::Texture *, QSGDistanceFieldGlyphNode *>::iterator subIt = m_subNodes.find(ite.key());
- if (subIt == m_subNodes.end()) {
- QSGDistanceFieldGlyphNode *subNode = new QSGDistanceFieldGlyphNode(m_glyph_cacheManager);
- subNode->setOwnerElement(m_ownerElement);
- subNode->setColor(m_color);
- subNode->setStyle(m_style);
- subNode->setStyleColor(m_styleColor);
- subNode->update();
- appendChildNode(subNode);
- subIt = m_subNodes.insert(ite.key(), subNode);
- }
-
QGlyphRun subNodeGlyphRun(m_glyphs);
subNodeGlyphRun.setGlyphIndexes(ite->indexes);
subNodeGlyphRun.setPositions(ite->positions);
- subIt.value()->setGlyphs(m_originalPosition, subNodeGlyphRun);
- subIt.value()->update();
- subIt.value()->updateGeometry(); // we have to explicity call this now as preprocess won't be called before it's rendered
+ QSGDistanceFieldGlyphNode *subNode = new QSGDistanceFieldGlyphNode(m_context);
+ subNode->setGlyphNodeType(SubGlyphNode);
+ subNode->setColor(m_color);
+ subNode->setStyle(m_style);
+ subNode->setStyleColor(m_styleColor);
+ subNode->setGlyphs(m_originalPosition, subNodeGlyphRun);
+ subNode->update();
+ subNode->updateGeometry(); // we have to explicity call this now as preprocess won't be called before it's rendered
+ appendChildNode(subNode);
++ite;
}
@@ -356,6 +356,8 @@ void QSGDistanceFieldGlyphNode::updateMaterial()
}
m_material->setGlyphCache(m_glyph_cache);
+ if (m_glyph_cache)
+ m_material->setFontScale(m_glyph_cache->fontScale(m_glyphs.rawFont().pixelSize()));
m_material->setColor(m_color);
setMaterial(m_material);
m_dirtyMaterial = false;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index c66b82c16e..cd988c70d7 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -151,8 +151,8 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q
bool updateRange = false;
if (oldMaterial == 0
- || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()) {
- m_fontScale = material->glyphCache()->fontScale();
+ || material->fontScale() != oldMaterial->fontScale()) {
+ m_fontScale = material->fontScale();
updateRange = true;
}
if (state.isMatrixDirty()) {
@@ -226,10 +226,8 @@ int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
const QSGDistanceFieldTextMaterial *other = static_cast<const QSGDistanceFieldTextMaterial *>(o);
if (m_glyph_cache != other->m_glyph_cache)
return m_glyph_cache - other->m_glyph_cache;
- if (m_glyph_cache->fontScale() != other->m_glyph_cache->fontScale()) {
- qreal s1 = m_glyph_cache->fontScale();
- qreal s2 = other->m_glyph_cache->fontScale();
- return int(s2 < s1) - int(s1 < s2);
+ if (m_fontScale != other->m_fontScale) {
+ return int(other->m_fontScale < m_fontScale) - int(m_fontScale < other->m_fontScale);
}
QRgb c1 = m_color.rgba();
QRgb c2 = other->m_color.rgba();
@@ -371,7 +369,7 @@ void DistanceFieldOutlineTextMaterialShader::updateState(const RenderState &stat
QSGDistanceFieldOutlineTextMaterial *oldMaterial = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldEffect);
if (oldMaterial == 0
- || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()
+ || material->fontScale() != oldMaterial->fontScale()
|| state.isMatrixDirty())
updateOutlineAlphaRange(material->glyphCache()->distanceFieldRadius());
}
@@ -410,7 +408,7 @@ protected:
virtual const char *vertexShader() const;
virtual const char *fragmentShader() const;
- void updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF& shift);
+ void updateShift(qreal fontScale, const QPointF& shift);
int m_shift_id;
};
@@ -434,17 +432,17 @@ void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState
QSGDistanceFieldShiftedStyleTextMaterial *oldMaterial = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldEffect);
if (oldMaterial == 0
- || oldMaterial->glyphCache()->fontScale() != material->glyphCache()->fontScale()
+ || oldMaterial->fontScale() != material->fontScale()
|| oldMaterial->shift() != material->shift()
|| oldMaterial->textureSize() != material->textureSize()) {
- updateShift(material->glyphCache(), material->shift());
+ updateShift(material->fontScale(), material->shift());
}
}
-void DistanceFieldShiftedStyleTextMaterialShader::updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF &shift)
+void DistanceFieldShiftedStyleTextMaterialShader::updateShift(qreal fontScale, const QPointF &shift)
{
- QPointF texel(1.0 / cache->fontScale() * shift.x(),
- 1.0 / cache->fontScale() * shift.y());
+ QPointF texel(1.0 / fontScale * shift.x(),
+ 1.0 / fontScale * shift.y());
program()->setUniformValue(m_shift_id, texel);
}
@@ -639,8 +637,8 @@ void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderStat
state.context()->functions()->glBlendColor(c.redF(), c.greenF(), c.blueF(), 1.0f);
}
- if (oldMaterial == 0 || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale())
- program()->setUniformValue(m_fontScale_id, GLfloat(material->glyphCache()->fontScale()));
+ if (oldMaterial == 0 || material->fontScale() != oldMaterial->fontScale())
+ program()->setUniformValue(m_fontScale_id, GLfloat(material->fontScale()));
if (oldMaterial == 0 || state.isMatrixDirty()) {
int viewportWidth = state.viewportRect().width();
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index 9406ee1bc8..146267c45d 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -51,12 +51,13 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
+class QSGContext;
class QSGDistanceFieldGlyphCacheManager;
class QSGDistanceFieldTextMaterial;
-class QSGDistanceFieldGlyphNode: public QSGGlyphNode
+class QSGDistanceFieldGlyphNode: public QSGGlyphNode, public QSGDistanceFieldGlyphConsumer
{
public:
- QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager);
+ QSGDistanceFieldGlyphNode(QSGContext *context);
~QSGDistanceFieldGlyphNode();
virtual QPointF baseLine() const { return m_baseLine; }
@@ -76,15 +77,22 @@ public:
void updateGeometry();
private:
+ enum DistanceFieldGlyphNodeType {
+ RootGlyphNode,
+ SubGlyphNode
+ };
+
+ void setGlyphNodeType(DistanceFieldGlyphNodeType type) { m_glyphNodeType = type; }
void updateMaterial();
+ DistanceFieldGlyphNodeType m_glyphNodeType;
QColor m_color;
QPointF m_baseLine;
+ QSGContext *m_context;
QSGDistanceFieldTextMaterial *m_material;
QPointF m_originalPosition;
QPointF m_position;
QGlyphRun m_glyphs;
- QSGDistanceFieldGlyphCacheManager *m_glyph_cacheManager;
QSGDistanceFieldGlyphCache *m_glyph_cache;
QSGGeometry m_geometry;
QQuickText::TextStyle m_style;
@@ -92,8 +100,7 @@ private:
AntialiasingMode m_antialiasingMode;
QRectF m_boundingRect;
const QSGDistanceFieldGlyphCache::Texture *m_texture;
- QHash<const QSGDistanceFieldGlyphCache::Texture *, QSGDistanceFieldGlyphNode *> m_subNodes;
- QList<QSGDistanceFieldGlyphNode *> m_nodesToDelete;
+ QLinkedList<QSGNode *> m_nodesToDelete;
struct GlyphInfo {
QVector<quint32> indexes;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
index c4af15a2af..8b2654e078 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-class QSGDistanceFieldTextMaterial: public QSGMaterial
+class Q_QUICK_EXPORT QSGDistanceFieldTextMaterial: public QSGMaterial
{
public:
QSGDistanceFieldTextMaterial();
@@ -67,6 +67,9 @@ public:
void setTexture(const QSGDistanceFieldGlyphCache::Texture * tex) { m_texture = tex; }
const QSGDistanceFieldGlyphCache::Texture * texture() const { return m_texture; }
+ void setFontScale(qreal fontScale) { m_fontScale = fontScale; }
+ qreal fontScale() const { return m_fontScale; }
+
QSize textureSize() const { return m_size; }
bool updateTextureSize();
@@ -76,9 +79,10 @@ protected:
QColor m_color;
QSGDistanceFieldGlyphCache *m_glyph_cache;
const QSGDistanceFieldGlyphCache::Texture *m_texture;
+ qreal m_fontScale;
};
-class QSGDistanceFieldStyledTextMaterial : public QSGDistanceFieldTextMaterial
+class Q_QUICK_EXPORT QSGDistanceFieldStyledTextMaterial : public QSGDistanceFieldTextMaterial
{
public:
QSGDistanceFieldStyledTextMaterial();
@@ -95,7 +99,7 @@ protected:
QColor m_styleColor;
};
-class QSGDistanceFieldOutlineTextMaterial : public QSGDistanceFieldStyledTextMaterial
+class Q_QUICK_EXPORT QSGDistanceFieldOutlineTextMaterial : public QSGDistanceFieldStyledTextMaterial
{
public:
QSGDistanceFieldOutlineTextMaterial();
@@ -105,7 +109,7 @@ public:
virtual QSGMaterialShader *createShader() const;
};
-class QSGDistanceFieldShiftedStyleTextMaterial : public QSGDistanceFieldStyledTextMaterial
+class Q_QUICK_EXPORT QSGDistanceFieldShiftedStyleTextMaterial : public QSGDistanceFieldStyledTextMaterial
{
public:
QSGDistanceFieldShiftedStyleTextMaterial();
@@ -121,14 +125,14 @@ protected:
QPointF m_shift;
};
-class QSGHiQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
+class Q_QUICK_EXPORT QSGHiQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
{
public:
virtual QSGMaterialType *type() const;
virtual QSGMaterialShader *createShader() const;
};
-class QSGLoQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
+class Q_QUICK_EXPORT QSGLoQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
{
public:
virtual QSGMaterialType *type() const;
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index f5fa18f87a..b6f7a228d2 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -23,6 +23,7 @@ SOURCES += \
# Util API
HEADERS += \
$$PWD/util/qsgareaallocator_p.h \
+ $$PWD/util/qsgdepthstencilbuffer_p.h \
$$PWD/util/qsgengine.h \
$$PWD/util/qsgflatcolormaterial.h \
$$PWD/util/qsgsimplematerial.h \
@@ -39,6 +40,7 @@ HEADERS += \
SOURCES += \
$$PWD/util/qsgareaallocator.cpp \
+ $$PWD/util/qsgdepthstencilbuffer.cpp \
$$PWD/util/qsgengine.cpp \
$$PWD/util/qsgflatcolormaterial.cpp \
$$PWD/util/qsgsimplerectnode.cpp \
diff --git a/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp
new file mode 100644
index 0000000000..bca57a3b6b
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgdepthstencilbuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QSGDepthStencilBuffer::QSGDepthStencilBuffer(QOpenGLContext *context, const Format &format)
+ : m_functions(context)
+ , m_manager(0)
+ , m_format(format)
+ , m_depthBuffer(0)
+ , m_stencilBuffer(0)
+{
+ // 'm_manager' is set by QSGDepthStencilBufferManager::insertBuffer().
+}
+
+QSGDepthStencilBuffer::~QSGDepthStencilBuffer()
+{
+ if (m_manager)
+ m_manager->m_buffers.remove(m_format);
+}
+
+void QSGDepthStencilBuffer::attach()
+{
+ m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, m_depthBuffer);
+ m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, m_stencilBuffer);
+}
+
+void QSGDepthStencilBuffer::detach()
+{
+ m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, 0);
+ m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, 0);
+}
+
+
+QSGDefaultDepthStencilBuffer::QSGDefaultDepthStencilBuffer(QOpenGLContext *context, const Format &format)
+ : QSGDepthStencilBuffer(context, format)
+{
+ const GLsizei width = format.size.width();
+ const GLsizei height = format.size.height();
+
+ if (format.attachments == (DepthAttachment | StencilAttachment)
+ && m_functions.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil))
+ {
+ m_functions.glGenRenderbuffers(1, &m_depthBuffer);
+ m_functions.glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
+ if (format.samples && m_functions.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
+ m_functions.glRenderbufferStorageMultisample(GL_RENDERBUFFER, format.samples,
+ GL_DEPTH24_STENCIL8, width, height);
+ } else {
+ m_functions.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+ }
+ m_stencilBuffer = m_depthBuffer;
+ }
+ if (!m_depthBuffer && (format.attachments & DepthAttachment)) {
+ m_functions.glGenRenderbuffers(1, &m_depthBuffer);
+ m_functions.glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
+#ifdef QT_OPENGL_ES
+ const GLenum internalFormat = m_functions.hasOpenGLExtension(QOpenGLExtensions::Depth24)
+ ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16;
+#else
+ const GLenum internalFormat = GL_DEPTH_COMPONENT;
+#endif
+ if (format.samples && m_functions.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
+ m_functions.glRenderbufferStorageMultisample(GL_RENDERBUFFER, format.samples,
+ internalFormat, width, height);
+ } else {
+ m_functions.glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
+ }
+ }
+ if (!m_stencilBuffer && (format.attachments & StencilAttachment)) {
+ m_functions.glGenRenderbuffers(1, &m_stencilBuffer);
+ m_functions.glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer);
+#ifdef QT_OPENGL_ES
+ const GLenum internalFormat = GL_STENCIL_INDEX8;
+#else
+ const GLenum internalFormat = GL_STENCIL_INDEX;
+#endif
+ if (format.samples && m_functions.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
+ m_functions.glRenderbufferStorageMultisample(GL_RENDERBUFFER, format.samples,
+ internalFormat, width, height);
+ } else {
+ m_functions.glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
+ }
+ }
+}
+
+QSGDefaultDepthStencilBuffer::~QSGDefaultDepthStencilBuffer()
+{
+ free();
+}
+
+void QSGDefaultDepthStencilBuffer::free()
+{
+ if (m_depthBuffer)
+ m_functions.glDeleteRenderbuffers(1, &m_depthBuffer);
+ if (m_stencilBuffer && m_stencilBuffer != m_depthBuffer)
+ m_functions.glDeleteRenderbuffers(1, &m_stencilBuffer);
+ m_depthBuffer = m_stencilBuffer = 0;
+}
+
+
+QSGDepthStencilBufferManager::~QSGDepthStencilBufferManager()
+{
+ for (Hash::const_iterator it = m_buffers.constBegin(); it != m_buffers.constEnd(); ++it) {
+ QSGDepthStencilBuffer *buffer = it.value().data();
+ buffer->free();
+ buffer->m_manager = 0;
+ }
+}
+
+QSharedPointer<QSGDepthStencilBuffer> QSGDepthStencilBufferManager::bufferForFormat(const QSGDepthStencilBuffer::Format &fmt)
+{
+ Hash::const_iterator it = m_buffers.constFind(fmt);
+ if (it != m_buffers.constEnd())
+ return it.value().toStrongRef();
+ return QSharedPointer<QSGDepthStencilBuffer>();
+}
+
+void QSGDepthStencilBufferManager::insertBuffer(const QSharedPointer<QSGDepthStencilBuffer> &buffer)
+{
+ Q_ASSERT(buffer->m_manager == 0);
+ Q_ASSERT(!m_buffers.contains(buffer->m_format));
+ buffer->m_manager = this;
+ m_buffers.insert(buffer->m_format, buffer.toWeakRef());
+}
+
+uint qHash(const QSGDepthStencilBuffer::Format &format)
+{
+ return qHash(qMakePair(format.size.width(), format.size.height()))
+ ^ (uint(format.samples) << 12) ^ (uint(format.attachments) << 28);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h b/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h
new file mode 100644
index 0000000000..0d8847feb4
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGDEPTHSTENCILBUFFER_P_H
+#define QSGDEPTHSTENCILBUFFER_P_H
+
+#include <QtCore/qsize.h>
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtGui/private/qopenglextensions_p.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGDepthStencilBufferManager;
+
+class QSGDepthStencilBuffer
+{
+public:
+ enum Attachment
+ {
+ NoAttachment = 0x00,
+ DepthAttachment = 0x01,
+ StencilAttachment = 0x02
+ };
+ Q_DECLARE_FLAGS(Attachments, Attachment)
+
+ struct Format
+ {
+ QSize size;
+ int samples;
+ QSGDepthStencilBuffer::Attachments attachments;
+ bool operator == (const Format &other) const;
+ };
+
+ QSGDepthStencilBuffer(QOpenGLContext *context, const Format &format);
+ virtual ~QSGDepthStencilBuffer();
+
+ // Attaches this depth stencil buffer to the currently bound FBO.
+ void attach();
+ // Detaches this depth stencil buffer from the currently bound FBO.
+ void detach();
+
+ QSize size() const { return m_format.size; }
+ int samples() const { return m_format.samples; }
+ Attachments attachments() const { return m_format.attachments; }
+
+protected:
+ virtual void free() = 0;
+
+ QOpenGLExtensions m_functions;
+ QSGDepthStencilBufferManager *m_manager;
+ Format m_format;
+ GLuint m_depthBuffer;
+ GLuint m_stencilBuffer;
+
+ friend class QSGDepthStencilBufferManager;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGDepthStencilBuffer::Attachments)
+
+inline bool QSGDepthStencilBuffer::Format::operator == (const Format &other) const
+{
+ return size == other.size && samples == other.samples && attachments == other.attachments;
+}
+
+
+class QSGDefaultDepthStencilBuffer : public QSGDepthStencilBuffer
+{
+public:
+ QSGDefaultDepthStencilBuffer(QOpenGLContext *context, const Format &format);
+ virtual ~QSGDefaultDepthStencilBuffer();
+
+protected:
+ virtual void free();
+};
+
+
+class QSGDepthStencilBufferManager
+{
+public:
+ QSGDepthStencilBufferManager(QOpenGLContext *ctx) : m_context(ctx) { }
+ ~QSGDepthStencilBufferManager();
+ QOpenGLContext *context() const { return m_context; }
+ QSharedPointer<QSGDepthStencilBuffer> bufferForFormat(const QSGDepthStencilBuffer::Format &fmt);
+ void insertBuffer(const QSharedPointer<QSGDepthStencilBuffer> &buffer);
+
+private:
+ typedef QHash<QSGDepthStencilBuffer::Format, QWeakPointer<QSGDepthStencilBuffer> > Hash;
+ QOpenGLContext *m_context;
+ Hash m_buffers;
+
+ friend class QSGDepthStencilBuffer;
+};
+
+extern uint qHash(const QSGDepthStencilBuffer::Format &format);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
index 76fdf97d80..ecfdf9b03c 100644
--- a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
@@ -62,16 +62,10 @@ static float defaultAntialiasingSpreadFunc(float glyphScale)
return range / glyphScale;
}
-QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(QSGContext *c)
- : sgCtx(c)
- , m_threshold_func(defaultThresholdFunc)
+QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager()
+ : m_threshold_func(defaultThresholdFunc)
, m_antialiasingSpread_func(defaultAntialiasingSpreadFunc)
{
-#ifndef QT_OPENGL_ES
- m_defaultAntialiasingMode = QSGGlyphNode::HighQualitySubPixelAntialiasing;
-#else
- m_defaultAntialiasingMode = QSGGlyphNode::GrayAntialiasing;
-#endif
}
QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
@@ -81,11 +75,22 @@ QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawFont &font)
{
- QRawFontPrivate *fontD = QRawFontPrivate::get(font);
- QHash<QFontEngine *, QSGDistanceFieldGlyphCache *>::iterator cache = m_caches.find(fontD->fontEngine);
- if (cache == m_caches.end())
- cache = m_caches.insert(fontD->fontEngine, sgCtx->createDistanceFieldGlyphCache(font));
- return cache.value();
+ QString key = QString::fromLatin1("%1_%2_%3_%4")
+ .arg(font.familyName())
+ .arg(font.styleName())
+ .arg(font.weight())
+ .arg(font.style());
+ return m_caches.value(key, 0);
+}
+
+void QSGDistanceFieldGlyphCacheManager::insertCache(const QRawFont &font, QSGDistanceFieldGlyphCache *cache)
+{
+ QString key = QString::fromLatin1("%1_%2_%3_%4")
+ .arg(font.familyName())
+ .arg(font.styleName())
+ .arg(font.weight())
+ .arg(font.style());
+ m_caches.insert(key, cache);
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
index 49391a737c..4ed4c28657 100644
--- a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
@@ -58,13 +58,11 @@ class QSGContext;
class Q_QUICK_EXPORT QSGDistanceFieldGlyphCacheManager
{
public:
- QSGDistanceFieldGlyphCacheManager(QSGContext *c);
+ QSGDistanceFieldGlyphCacheManager();
~QSGDistanceFieldGlyphCacheManager();
QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
-
- QSGGlyphNode::AntialiasingMode defaultAntialiasingMode() const { return m_defaultAntialiasingMode; }
- void setDefaultAntialiasingMode(QSGGlyphNode::AntialiasingMode mode) { m_defaultAntialiasingMode = mode; }
+ void insertCache(const QRawFont &font, QSGDistanceFieldGlyphCache *cache);
ThresholdFunc thresholdFunc() const { return m_threshold_func; }
void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
@@ -73,9 +71,7 @@ public:
void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
private:
- QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches;
-
- QSGContext *sgCtx;
+ QHash<QString, QSGDistanceFieldGlyphCache *> m_caches;
QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode;
ThresholdFunc m_threshold_func;
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index adf4242cdc..8dadab620a 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -527,6 +527,8 @@ QPointF QQuickPath::sequentialPointAt(qreal p, qreal *angle) const
QPointF QQuickPath::sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle)
{
+ Q_ASSERT(p >= 0.0 && p <= 1.0);
+
if (!prevBez.isValid)
return p > .5 ? backwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle) :
forwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle);
diff --git a/src/quick/util/qquickpathinterpolator.cpp b/src/quick/util/qquickpathinterpolator.cpp
index 2b5fb62872..ee1424b70f 100644
--- a/src/quick/util/qquickpathinterpolator.cpp
+++ b/src/quick/util/qquickpathinterpolator.cpp
@@ -102,6 +102,8 @@ qreal QQuickPathInterpolator::progress() const
void QQuickPathInterpolator::setProgress(qreal progress)
{
+ progress = qMin(qMax(progress, (qreal)0.0), (qreal)1.0);
+
if (progress == _progress)
return;
_progress = progress;
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro
index 7669aaa83c..81ca29a2e0 100644
--- a/tests/auto/qml/debugger/debugger.pro
+++ b/tests/auto/qml/debugger/debugger.pro
@@ -1,9 +1,7 @@
TEMPLATE = subdirs
-PRIVATETESTS += \
+PUBLICTESTS += \
qqmlenginedebugservice \
- qqmldebugclient \
- qqmldebugservice \
qqmldebugjs \
qqmlinspector \
qqmlprofilerservice \
@@ -11,6 +9,12 @@ PRIVATETESTS += \
qv8profilerservice \
qdebugmessageservice
+PRIVATETESTS += \
+ qqmldebugclient \
+ qqmldebugservice
+
+SUBDIRS += $$PUBLICTESTS
+
contains(QT_CONFIG, private_tests) {
SUBDIRS += $$PRIVATETESTS
}
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro
index 4b5bf60ace..64f7274f6f 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro
+++ b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qdebugmessageservice
-QT += network qml-private testlib
+QT += qml network testlib
macx:CONFIG -= app_bundle
SOURCES += tst_qdebugmessageservice.cpp
diff --git a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro
index f631929427..e6869fe5cb 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro
+++ b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro
@@ -8,4 +8,4 @@ INCLUDEPATH += ../shared
include(../shared/debugutil.pri)
CONFIG += parallel_test
-QT += qml-private network testlib
+QT += qml network testlib
diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
index 4a6efb469d..8a8c0e5081 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
+++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -46,7 +46,7 @@
#include <QDebug>
#include <QBuffer>
-#include <private/qpacketprotocol_p.h>
+#include "../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h"
#include "debugutil_p.h"
diff --git a/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro b/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro
index 22a4df7dc9..60355f1527 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro
+++ b/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro
@@ -2,7 +2,10 @@ CONFIG += testcase
TARGET = tst_qqmldebugclient
macx:CONFIG -= app_bundle
-SOURCES += tst_qqmldebugclient.cpp
+HEADERS += ../shared/qqmldebugtestservice.h
+
+SOURCES += tst_qqmldebugclient.cpp \
+ ../shared/qqmldebugtestservice.cpp
INCLUDEPATH += ../shared
include(../shared/debugutil.pri)
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index 1682913bc3..2d52ea9f50 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -48,6 +48,7 @@
#include <QtQml/qqmlengine.h>
#include "debugutil_p.h"
+#include "qqmldebugtestservice.h"
#define PORT 13770
#define STR_PORT "13770"
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
index 1f0f9e22c9..0a1a5eb610 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
@@ -47,7 +47,9 @@ Item {
Component.onCompleted: {
//Comment
- var b = 6;
+ var x = 6;
}
+
+ width : height + 2
}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
index 7c3a2ea042..c06fd84e58 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
+++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qqmldebugjs
-QT += qml-private testlib
+QT += qml testlib
macx:CONFIG -= app_bundle
SOURCES += tst_qqmldebugjs.cpp
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index f4a9a4add7..8293ec6cda 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -191,6 +191,7 @@ private slots:
void setBreakpointInScriptInDifferentFile();
void setBreakpointInScriptOnComment();
void setBreakpointInScriptOnEmptyLine();
+ void setBreakpointInScriptOnOptimizedBinding();
void setBreakpointInScriptWithCondition();
//void setBreakpointInFunction(); //NOT SUPPORTED
void setBreakpointOnEvent();
@@ -1019,9 +1020,6 @@ bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode)
process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene");
client = new QJSDebugClient(connection);
- QStringList systemEnvironment = QProcess::systemEnvironment();
- systemEnvironment << "QML_DISABLE_OPTIMIZER=1";
- process->setEnvironment(systemEnvironment);
if (blockMode)
process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile));
else
@@ -1295,6 +1293,26 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
}
+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 = 52;
+ QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
+
+ client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
+ client->connect();
+ QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
+}
+
void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
{
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
diff --git a/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro b/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro
index dc2039615a..bbf05b177c 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro
+++ b/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro
@@ -2,7 +2,11 @@ CONFIG += testcase
TARGET = tst_qqmldebugservice
macx:CONFIG -= app_bundle
-SOURCES += tst_qqmldebugservice.cpp
+HEADERS += ../shared/qqmldebugtestservice.h
+
+SOURCES += tst_qqmldebugservice.cpp \
+ ../shared/qqmldebugtestservice.cpp
+
INCLUDEPATH += ../shared
include(../../../shared/util.pri)
include(../shared/debugutil.pri)
diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
index 6e14c03a4c..8eb1523af9 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -47,11 +47,10 @@
#include <QtQml/qqmlengine.h>
-#include <private/qqmldebugservice_p.h>
-
#include "../../../shared/util.h"
#include "debugutil_p.h"
#include "qqmldebugclient.h"
+#include "qqmldebugtestservice.h"
#define PORT 13769
#define STR_PORT "13769"
@@ -204,7 +203,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:" STR_PORT;
+ char arg[] = "-qmljsdebugger=port:" STR_PORT ",host:127.0.0.1";
_argv[_argc - 1] = arg;
QGuiApplication app(_argc, _argv);
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp
new file mode 100644
index 0000000000..9639a36065
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp
@@ -0,0 +1,460 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlenginedebugclient.h"
+
+struct QmlObjectData {
+ QUrl url;
+ int lineNumber;
+ int columnNumber;
+ QString idString;
+ QString objectName;
+ QString objectType;
+ int objectId;
+ int contextId;
+};
+
+QDataStream &operator>>(QDataStream &ds, QmlObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
+ return ds;
+}
+
+struct QmlObjectProperty {
+ enum Type { Unknown, Basic, Object, List, SignalProperty };
+ Type type;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal;
+};
+
+QDataStream &operator>>(QDataStream &ds, QmlObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QmlObjectProperty::Type)type;
+ return ds;
+}
+
+QQmlEngineDebugClient::QQmlEngineDebugClient(
+ QQmlDebugConnection *connection)
+ : QQmlDebugClient(QLatin1String("QmlDebugger"), connection),
+ m_nextId(0),
+ m_valid(false)
+{
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QmlDebugPropertyReference &property, bool *success)
+{
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_PROPERTY") << id << property.objectDebugId
+ << property.name.toUtf8();
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QmlDebugContextReference &, const QString &, bool *success)
+{
+ *success = false;
+ qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QmlDebugObjectReference &object, const QString &expr,
+ bool *success)
+{
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.debugId << expr;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QmlDebugObjectReference &object, bool *success)
+{
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_OBJECT") << id << object.debugId;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QmlDebugFileReference &, bool *success)
+{
+ *success = false;
+ qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success)
+{
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("NO_WATCH") << id;
+ sendMessage(message);
+ *success = true;
+ }
+}
+
+quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success)
+{
+ m_engines.clear();
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_ENGINES") << id;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryRootContexts(
+ const QmlDebugEngineReference &engine, bool *success)
+{
+ m_rootContext = QmlDebugContextReference();
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && engine.debugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_OBJECTS") << id << engine.debugId;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObject(
+ const QmlDebugObjectReference &object, bool *success)
+{
+ m_object = QmlDebugObjectReference();
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << id << object.debugId << false <<
+ true;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObjectRecursive(
+ const QmlDebugObjectReference &object, bool *success)
+{
+ m_object = QmlDebugObjectReference();
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << id << object.debugId << true <<
+ true;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryExpressionResult(
+ int objectDebugId, const QString &expr, bool *success)
+{
+ m_exprResult = QVariant();
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::setBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ QString source, int line,
+ bool *success)
+{
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName
+ << bindingExpression << isLiteralValue << source << line;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::resetBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ bool *success)
+{
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::setMethodBody(
+ int objectDebugId, const QString &methodName,
+ const QString &methodBody, bool *success)
+{
+ quint32 id;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId
+ << methodName << methodBody;
+ sendMessage(message);
+ *success = true;
+ }
+ return id;
+}
+
+void QQmlEngineDebugClient::decode(QDataStream &ds,
+ QmlDebugObjectReference &o,
+ bool simple)
+{
+ QmlObjectData data;
+ ds >> data;
+ o.debugId = data.objectId;
+ o.className = data.objectType;
+ o.idString = data.idString;
+ o.name = data.objectName;
+ o.source.url = data.url;
+ o.source.lineNumber = data.lineNumber;
+ o.source.columnNumber = data.columnNumber;
+ o.contextDebugId = data.contextId;
+
+ if (simple)
+ return;
+
+ int childCount;
+ bool recur;
+ ds >> childCount >> recur;
+
+ for (int ii = 0; ii < childCount; ++ii) {
+ o.children.append(QmlDebugObjectReference());
+ decode(ds, o.children.last(), !recur);
+ }
+
+ int propCount;
+ ds >> propCount;
+
+ for (int ii = 0; ii < propCount; ++ii) {
+ QmlObjectProperty data;
+ ds >> data;
+ QmlDebugPropertyReference prop;
+ prop.objectDebugId = o.debugId;
+ prop.name = data.name;
+ prop.binding = data.binding;
+ prop.hasNotifySignal = data.hasNotifySignal;
+ prop.valueTypeName = data.valueTypeName;
+ switch (data.type) {
+ case QmlObjectProperty::Basic:
+ case QmlObjectProperty::List:
+ case QmlObjectProperty::SignalProperty:
+ {
+ prop.value = data.value;
+ break;
+ }
+ case QmlObjectProperty::Object:
+ {
+ QmlDebugObjectReference obj;
+ obj.debugId = prop.value.toInt();
+ prop.value = qVariantFromValue(obj);
+ break;
+ }
+ case QmlObjectProperty::Unknown:
+ break;
+ }
+ o.properties << prop;
+ }
+}
+
+void QQmlEngineDebugClient::decode(QDataStream &ds,
+ QmlDebugContextReference &c)
+{
+ ds >> c.name >> c.debugId;
+
+ int contextCount;
+ ds >> contextCount;
+
+ for (int ii = 0; ii < contextCount; ++ii) {
+ c.contexts.append(QmlDebugContextReference());
+ decode(ds, c.contexts.last());
+ }
+
+ int objectCount;
+ ds >> objectCount;
+
+ for (int ii = 0; ii < objectCount; ++ii) {
+ QmlDebugObjectReference obj;
+ decode(ds, obj, true);
+
+ obj.contextDebugId = c.debugId;
+ c.objects << obj;
+ }
+}
+
+void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ m_valid = false;
+ QDataStream ds(data);
+ int queryId;
+ QByteArray type;
+ ds >> type >> queryId;
+
+ //qDebug() << "QQmlEngineDebugPrivate::message()" << type;
+
+ if (type == "LIST_ENGINES_R") {
+ int count;
+ ds >> count;
+
+ m_engines.clear();
+ for (int ii = 0; ii < count; ++ii) {
+ QmlDebugEngineReference eng;
+ ds >> eng.name;
+ ds >> eng.debugId;
+ m_engines << eng;
+ }
+ } else if (type == "LIST_OBJECTS_R") {
+ if (!ds.atEnd())
+ decode(ds, m_rootContext);
+
+ } else if (type == "FETCH_OBJECT_R") {
+ if (!ds.atEnd())
+ decode(ds, m_object, false);
+
+ } else if (type == "EVAL_EXPRESSION_R") {;
+ ds >> m_exprResult;
+
+ } else if (type == "WATCH_PROPERTY_R") {
+ ds >> m_valid;
+
+ } else if (type == "WATCH_OBJECT_R") {
+ ds >> m_valid;
+
+ } else if (type == "WATCH_EXPR_OBJECT_R") {
+ ds >> m_valid;
+
+ } else if (type == "UPDATE_WATCH") {
+ int debugId;
+ QByteArray name;
+ QVariant value;
+ ds >> debugId >> name >> value;
+ emit valueChanged(name, value);
+ return;
+
+ } else if (type == "OBJECT_CREATED") {
+ emit newObjects();
+ return;
+ } else if (type == "SET_BINDING_R") {
+ ds >> m_valid;
+ } else if (type == "RESET_BINDING_R") {
+ ds >> m_valid;
+ } else if (type == "SET_METHOD_BODY_R") {
+ ds >> m_valid;
+ } else if (type == "NO_WATCH_R") {
+ ds >> m_valid;
+ }
+ emit result();
+}
+
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.h b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.h
new file mode 100644
index 0000000000..62f9b15824
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.h
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLENGINEDEBUGCLIENT_H
+#define QQMLENGINEDEBUGCLIENT_H
+
+#include "qqmldebugclient.h"
+
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+class QQmlDebugConnection;
+
+struct QmlDebugPropertyReference
+{
+ QmlDebugPropertyReference()
+ : objectDebugId(-1), hasNotifySignal(false)
+ {
+ }
+
+ QmlDebugPropertyReference &operator=(
+ const QmlDebugPropertyReference &o)
+ {
+ objectDebugId = o.objectDebugId; name = o.name; value = o.value;
+ valueTypeName = o.valueTypeName; binding = o.binding;
+ hasNotifySignal = o.hasNotifySignal;
+ return *this;
+ }
+
+ int objectDebugId;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal;
+};
+
+struct QmlDebugFileReference
+{
+ QmlDebugFileReference()
+ : lineNumber(-1), columnNumber(-1)
+ {
+ }
+
+ QmlDebugFileReference &operator=(
+ const QmlDebugFileReference &o)
+ {
+ url = o.url; lineNumber = o.lineNumber; columnNumber = o.columnNumber;
+ return *this;
+ }
+
+ QUrl url;
+ int lineNumber;
+ int columnNumber;
+};
+
+struct QmlDebugObjectReference
+{
+ QmlDebugObjectReference()
+ : debugId(-1), contextDebugId(-1)
+ {
+ }
+
+ QmlDebugObjectReference(int id)
+ : debugId(id), contextDebugId(-1)
+ {
+ }
+
+ QmlDebugObjectReference &operator=(
+ const QmlDebugObjectReference &o)
+ {
+ debugId = o.debugId; className = o.className; idString = o.idString;
+ name = o.name; source = o.source; contextDebugId = o.contextDebugId;
+ properties = o.properties; children = o.children;
+ return *this;
+ }
+ int debugId;
+ QString className;
+ QString idString;
+ QString name;
+ QmlDebugFileReference source;
+ int contextDebugId;
+ QList<QmlDebugPropertyReference> properties;
+ QList<QmlDebugObjectReference> children;
+};
+
+Q_DECLARE_METATYPE(QmlDebugObjectReference)
+
+struct QmlDebugContextReference
+{
+ QmlDebugContextReference()
+ : debugId(-1)
+ {
+ }
+
+ QmlDebugContextReference &operator=(
+ const QmlDebugContextReference &o)
+ {
+ debugId = o.debugId; name = o.name; objects = o.objects;
+ contexts = o.contexts;
+ return *this;
+ }
+
+ int debugId;
+ QString name;
+ QList<QmlDebugObjectReference> objects;
+ QList<QmlDebugContextReference> contexts;
+};
+
+struct QmlDebugEngineReference
+{
+ QmlDebugEngineReference()
+ : debugId(-1)
+ {
+ }
+
+ QmlDebugEngineReference(int id)
+ : debugId(id)
+ {
+ }
+
+ QmlDebugEngineReference &operator=(
+ const QmlDebugEngineReference &o)
+ {
+ debugId = o.debugId; name = o.name;
+ return *this;
+ }
+
+ int debugId;
+ QString name;
+};
+
+class QQmlEngineDebugClient : public QQmlDebugClient
+{
+ Q_OBJECT
+public:
+ explicit QQmlEngineDebugClient(QQmlDebugConnection *conn);
+
+ quint32 addWatch(const QmlDebugPropertyReference &,
+ bool *success);
+ quint32 addWatch(const QmlDebugContextReference &, const QString &,
+ bool *success);
+ quint32 addWatch(const QmlDebugObjectReference &, const QString &,
+ bool *success);
+ quint32 addWatch(const QmlDebugObjectReference &,
+ bool *success);
+ quint32 addWatch(const QmlDebugFileReference &,
+ bool *success);
+
+ void removeWatch(quint32 watch, bool *success);
+
+ quint32 queryAvailableEngines(bool *success);
+ quint32 queryRootContexts(const QmlDebugEngineReference &,
+ bool *success);
+ quint32 queryObject(const QmlDebugObjectReference &,
+ bool *success);
+ quint32 queryObjectRecursive(const QmlDebugObjectReference &,
+ bool *success);
+ quint32 queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ bool *success);
+ quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ QString source, int line, bool *success);
+ quint32 resetBindingForObject(int objectDebugId,
+ const QString &propertyName, bool *success);
+ quint32 setMethodBody(int objectDebugId, const QString &methodName,
+ const QString &methodBody, bool *success);
+
+ quint32 getId() { return m_nextId++; }
+
+ void decode(QDataStream &, QmlDebugContextReference &);
+ void decode(QDataStream &, QmlDebugObjectReference &, bool simple);
+
+ QList<QmlDebugEngineReference> engines() { return m_engines; }
+ QmlDebugContextReference rootContext() { return m_rootContext; }
+ QmlDebugObjectReference object() { return m_object; }
+ QVariant resultExpr() { return m_exprResult; }
+ bool valid() { return m_valid; }
+
+signals:
+ void newObjects();
+ void valueChanged(QByteArray,QVariant);
+ void result();
+
+protected:
+ void messageReceived(const QByteArray &);
+
+private:
+ quint32 m_nextId;
+ bool m_valid;
+ QList<QmlDebugEngineReference> m_engines;
+ QmlDebugContextReference m_rootContext;
+ QmlDebugObjectReference m_object;
+ QVariant m_exprResult;
+};
+
+#endif // QQMLENGINEDEBUGCLIENT_H
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro
index 0b92a726b5..0212d11cd1 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro
@@ -2,9 +2,15 @@ CONFIG += testcase
TARGET = tst_qqmlenginedebugservice
macx:CONFIG -= app_bundle
-SOURCES += tst_qqmlenginedebugservice.cpp
+HEADERS += \
+ qqmlenginedebugclient.h
+
+SOURCES += \
+ tst_qqmlenginedebugservice.cpp \
+ qqmlenginedebugclient.cpp
INCLUDEPATH += ../shared
+include(../../../shared/util.pri)
include(../shared/debugutil.pri)
CONFIG += parallel_test declarative_debug
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index e409f3c8b6..e84e6623c1 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -59,27 +59,45 @@
#include <private/qqmlproperty_p.h>
#include "debugutil_p.h"
-#include "qqmlenginedebug_p.h"
+#include "qqmlenginedebugclient.h"
-Q_DECLARE_METATYPE(QQmlDebugWatch::State)
+#include "../../../shared/util.h"
+
+#define QVERIFYOBJECT(statement) \
+ do {\
+ if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\
+ return QmlDebugObjectReference();\
+ }\
+ } while (0)
+
+class NonScriptProperty : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(int nonScriptProp READ nonScriptProp WRITE setNonScriptProp NOTIFY nonScriptPropChanged SCRIPTABLE false)
+public:
+ int nonScriptProp() const { return 0; }
+ void setNonScriptProp(int) {}
+signals:
+ void nonScriptPropChanged();
+};
+QML_DECLARE_TYPE(NonScriptProperty)
class tst_QQmlEngineDebugService : public QObject
{
Q_OBJECT
private:
- QQmlDebugObjectReference findRootObject(int context = 0, bool recursive = false);
- QQmlDebugPropertyReference findProperty(const QList<QQmlDebugPropertyReference> &props, const QString &name) const;
- void waitForQuery(QQmlDebugQuery *query);
-
- void recursiveObjectTest(QObject *o, const QQmlDebugObjectReference &oref, bool recursive) const;
+ QmlDebugObjectReference findRootObject(int context = 0,
+ bool recursive = false);
+ QmlDebugPropertyReference findProperty(
+ const QList<QmlDebugPropertyReference> &props,
+ const QString &name) const;
- void recursiveCompareObjects(const QQmlDebugObjectReference &a, const QQmlDebugObjectReference &b) const;
- void recursiveCompareContexts(const QQmlDebugContextReference &a, const QQmlDebugContextReference &b) const;
- void compareProperties(const QQmlDebugPropertyReference &a, const QQmlDebugPropertyReference &b) const;
+ void recursiveObjectTest(QObject *o,
+ const QmlDebugObjectReference &oref,
+ bool recursive) const;
QQmlDebugConnection *m_conn;
- QQmlEngineDebug *m_dbg;
+ QQmlEngineDebugClient *m_dbg;
QQmlEngine *m_engine;
QQuickItem *m_rootItem;
@@ -103,90 +121,62 @@ private slots:
void queryExpressionResult();
void queryExpressionResult_data();
- void tst_QQmlDebugFileReference();
- void tst_QQmlDebugEngineReference();
- void tst_QQmlDebugObjectReference();
- void tst_QQmlDebugContextReference();
- void tst_QQmlDebugPropertyReference();
-
void setBindingForObject();
void setMethodBody();
void queryObjectTree();
void setBindingInStates();
};
-class NonScriptProperty : public QObject {
- Q_OBJECT
- Q_PROPERTY(int nonScriptProp READ nonScriptProp WRITE setNonScriptProp NOTIFY nonScriptPropChanged SCRIPTABLE false)
-public:
- int nonScriptProp() const { return 0; }
- void setNonScriptProp(int) {}
-signals:
- void nonScriptPropChanged();
-};
-QML_DECLARE_TYPE(NonScriptProperty)
-
-
-QQmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject(int context, bool recursive)
-{
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines);
-
- if (q_engines->engines().count() == 0)
- return QQmlDebugObjectReference();
- QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
- waitForQuery(q_context);
-
- if (q_context->rootContext().contexts().count() == 0 ||
- q_context->rootContext().contexts().last().objects().count() == 0)
- return QQmlDebugObjectReference();
-
- //Contexts are in a stack
- int count = q_context->rootContext().contexts().count();
- QQmlDebugObjectQuery *q_obj = recursive ?
- m_dbg->queryObjectRecursive(q_context->rootContext().contexts()[count - context - 1].objects()[0], this) :
- m_dbg->queryObject(q_context->rootContext().contexts()[count - context - 1].objects()[0], this);
- waitForQuery(q_obj);
-
- QQmlDebugObjectReference result = q_obj->object();
-
- delete q_engines;
- delete q_context;
- delete q_obj;
-
- return result;
+QmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject(
+ int context, bool recursive)
+{
+ bool success = false;
+ m_dbg->queryAvailableEngines(&success);
+ QVERIFYOBJECT(success);
+ QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+
+ QVERIFYOBJECT(m_dbg->engines().count());
+ m_dbg->queryRootContexts(m_dbg->engines()[0].debugId, &success);
+ QVERIFYOBJECT(success);
+ QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+
+ QVERIFYOBJECT(m_dbg->rootContext().contexts.count());
+ QVERIFYOBJECT(m_dbg->rootContext().contexts.last().objects.count());
+ int count = m_dbg->rootContext().contexts.count();
+ recursive ? m_dbg->queryObjectRecursive(m_dbg->rootContext().contexts[count - context - 1].objects[0],
+ &success) :
+ m_dbg->queryObject(m_dbg->rootContext().contexts[count - context - 1].objects[0], &success);
+ QVERIFYOBJECT(success);
+ QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+
+ return m_dbg->object();
}
-QQmlDebugPropertyReference tst_QQmlEngineDebugService::findProperty(const QList<QQmlDebugPropertyReference> &props, const QString &name) const
+QmlDebugPropertyReference tst_QQmlEngineDebugService::findProperty(
+ const QList<QmlDebugPropertyReference> &props, const QString &name) const
{
- foreach(const QQmlDebugPropertyReference &p, props) {
- if (p.name() == name)
+ foreach (const QmlDebugPropertyReference &p, props) {
+ if (p.name == name)
return p;
}
- return QQmlDebugPropertyReference();
-}
-
-void tst_QQmlEngineDebugService::waitForQuery(QQmlDebugQuery *query)
-{
- QVERIFY(query);
- QCOMPARE(query->parent(), qobject_cast<QObject*>(this));
- QVERIFY(query->state() == QQmlDebugQuery::Waiting);
- if (!QQmlDebugTest::waitForSignal(query, SIGNAL(stateChanged(QQmlDebugQuery::State))))
- QFAIL("query timed out");
+ return QmlDebugPropertyReference();
}
-void tst_QQmlEngineDebugService::recursiveObjectTest(QObject *o, const QQmlDebugObjectReference &oref, bool recursive) const
+void tst_QQmlEngineDebugService::recursiveObjectTest(
+ QObject *o, const QmlDebugObjectReference &oref, bool recursive) const
{
const QMetaObject *meta = o->metaObject();
QQmlType *type = QQmlMetaType::qmlType(meta);
- QString className = type ? QString(type->qmlTypeName()) : QString(meta->className());
+ QString className = type ? QString(type->qmlTypeName())
+ : QString(meta->className());
className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1);
- QCOMPARE(oref.debugId(), QQmlDebugService::idForObject(o));
- QCOMPARE(oref.name(), o->objectName());
- QCOMPARE(oref.className(), className);
- QCOMPARE(oref.contextDebugId(), QQmlDebugService::idForObject(qmlContext(o)));
+ QCOMPARE(oref.debugId, QQmlDebugService::idForObject(o));
+ QCOMPARE(oref.name, o->objectName());
+ QCOMPARE(oref.className, className);
+ QCOMPARE(oref.contextDebugId, QQmlDebugService::idForObject(
+ qmlContext(o)));
const QObjectList &children = o->children();
for (int i=0; i<children.count(); i++) {
@@ -196,26 +186,27 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(QObject *o, const QQmlDebug
int debugId = QQmlDebugService::idForObject(child);
QVERIFY(debugId >= 0);
- QQmlDebugObjectReference cref;
- foreach (const QQmlDebugObjectReference &ref, oref.children()) {
- if (ref.debugId() == debugId) {
+ QmlDebugObjectReference cref;
+ foreach (const QmlDebugObjectReference &ref, oref.children) {
+ if (ref.debugId == debugId) {
cref = ref;
break;
}
}
- QVERIFY(cref.debugId() >= 0);
+ QVERIFY(cref.debugId >= 0);
if (recursive)
recursiveObjectTest(child, cref, true);
}
- foreach (const QQmlDebugPropertyReference &p, oref.properties()) {
- QCOMPARE(p.objectDebugId(), QQmlDebugService::idForObject(o));
+ foreach (const QmlDebugPropertyReference &p, oref.properties) {
+ QCOMPARE(p.objectDebugId, QQmlDebugService::idForObject(o));
// signal properties are fake - they are generated from QQmlBoundSignal children
- if (p.name().startsWith("on") && p.name().length() > 2 && p.name()[2].isUpper()) {
- QList<QQmlBoundSignal*> signalHandlers = o->findChildren<QQmlBoundSignal*>();
- QString signal = p.value().toString();
+ if (p.name.startsWith("on") && p.name.length() > 2 && p.name[2].isUpper()) {
+ QList<QQmlBoundSignal*> signalHandlers =
+ o->findChildren<QQmlBoundSignal*>();
+ QString signal = p.value.toString();
bool found = false;
for (int i = 0; i < signalHandlers.count(); ++i)
if (signalHandlers.at(i)->expression()->expression() == signal) {
@@ -223,86 +214,40 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(QObject *o, const QQmlDebug
break;
}
QVERIFY(found);
- QVERIFY(p.valueTypeName().isEmpty());
- QVERIFY(p.binding().isEmpty());
- QVERIFY(!p.hasNotifySignal());
+ QVERIFY(p.valueTypeName.isEmpty());
+ QVERIFY(p.binding.isEmpty());
+ QVERIFY(!p.hasNotifySignal);
continue;
}
- QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name().toUtf8().constData()));
+ QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name.toUtf8().constData()));
- QCOMPARE(p.name(), QString::fromUtf8(pmeta.name()));
+ QCOMPARE(p.name, QString::fromUtf8(pmeta.name()));
- if (pmeta.type() < QVariant::UserType && pmeta.userType() != QMetaType::QVariant) // TODO test complex types
- QCOMPARE(p.value(), pmeta.read(o));
+ if (pmeta.type() < QVariant::UserType && pmeta.userType() !=
+ QMetaType::QVariant) // TODO test complex types
+ QCOMPARE(p.value , pmeta.read(o));
- if (p.name() == "parent")
- QVERIFY(p.valueTypeName() == "QGraphicsObject*" || p.valueTypeName() == "QQuickItem*");
+ if (p.name == "parent")
+ QVERIFY(p.valueTypeName == "QGraphicsObject*" ||
+ p.valueTypeName == "QQuickItem*");
else
- QCOMPARE(p.valueTypeName(), QString::fromUtf8(pmeta.typeName()));
+ QCOMPARE(p.valueTypeName, QString::fromUtf8(pmeta.typeName()));
- QQmlAbstractBinding *binding =
- QQmlPropertyPrivate::binding(QQmlProperty(o, p.name()));
+ QQmlAbstractBinding *binding =
+ QQmlPropertyPrivate::binding(
+ QQmlProperty(o, p.name));
if (binding)
- QCOMPARE(binding->expression(), p.binding());
+ QCOMPARE(binding->expression(), p.binding);
- QCOMPARE(p.hasNotifySignal(), pmeta.hasNotifySignal());
+ QCOMPARE(p.hasNotifySignal, pmeta.hasNotifySignal());
QVERIFY(pmeta.isValid());
}
}
-void tst_QQmlEngineDebugService::recursiveCompareObjects(const QQmlDebugObjectReference &a, const QQmlDebugObjectReference &b) const
-{
- QCOMPARE(a.debugId(), b.debugId());
- QCOMPARE(a.className(), b.className());
- QCOMPARE(a.name(), b.name());
- QCOMPARE(a.contextDebugId(), b.contextDebugId());
-
- QCOMPARE(a.source().url(), b.source().url());
- QCOMPARE(a.source().lineNumber(), b.source().lineNumber());
- QCOMPARE(a.source().columnNumber(), b.source().columnNumber());
-
- QCOMPARE(a.properties().count(), b.properties().count());
- QCOMPARE(a.children().count(), b.children().count());
-
- QList<QQmlDebugPropertyReference> aprops = a.properties();
- QList<QQmlDebugPropertyReference> bprops = b.properties();
-
- for (int i=0; i<aprops.count(); i++)
- compareProperties(aprops[i], bprops[i]);
-
- for (int i=0; i<a.children().count(); i++)
- recursiveCompareObjects(a.children()[i], b.children()[i]);
-}
-
-void tst_QQmlEngineDebugService::recursiveCompareContexts(const QQmlDebugContextReference &a, const QQmlDebugContextReference &b) const
-{
- QCOMPARE(a.debugId(), b.debugId());
- QCOMPARE(a.name(), b.name());
- QCOMPARE(a.objects().count(), b.objects().count());
- QCOMPARE(a.contexts().count(), b.contexts().count());
-
- for (int i=0; i<a.objects().count(); i++)
- recursiveCompareObjects(a.objects()[i], b.objects()[i]);
-
- for (int i=0; i<a.contexts().count(); i++)
- recursiveCompareContexts(a.contexts()[i], b.contexts()[i]);
-}
-
-void tst_QQmlEngineDebugService::compareProperties(const QQmlDebugPropertyReference &a, const QQmlDebugPropertyReference &b) const
-{
- QCOMPARE(a.objectDebugId(), b.objectDebugId());
- QCOMPARE(a.name(), b.name());
- QCOMPARE(a.value(), b.value());
- QCOMPARE(a.valueTypeName(), b.valueTypeName());
- QCOMPARE(a.binding(), b.binding());
- QCOMPARE(a.hasNotifySignal(), b.hasNotifySignal());
-}
-
void tst_QQmlEngineDebugService::initTestCase()
{
- qRegisterMetaType<QQmlDebugWatch::State>();
qmlRegisterType<NonScriptProperty>("Test", 1, 0, "NonScriptPropertyElement");
QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Waiting for connection on port 3768...");
@@ -394,13 +339,12 @@ void tst_QQmlEngineDebugService::initTestCase()
bool ok = m_conn->waitForConnected();
QVERIFY(ok);
QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
- m_dbg = new QQmlEngineDebug(m_conn, this);
- QTRY_VERIFY(m_dbg->state() == QQmlEngineDebug::Enabled);
+ m_dbg = new QQmlEngineDebugClient(m_conn);
+ QTRY_VERIFY(m_dbg->state() == QQmlEngineDebugClient::Enabled);
}
void tst_QQmlEngineDebugService::cleanupTestCase()
{
- delete m_dbg;
delete m_conn;
qDeleteAll(m_components);
delete m_engine;
@@ -408,7 +352,8 @@ void tst_QQmlEngineDebugService::cleanupTestCase()
void tst_QQmlEngineDebugService::setMethodBody()
{
- QQmlDebugObjectReference obj = findRootObject(2);
+ bool success;
+ QmlDebugObjectReference obj = findRootObject(2);
QObject *root = m_components.at(2);
// Without args
@@ -419,8 +364,10 @@ void tst_QQmlEngineDebugService::setMethodBody()
QVERIFY(rv == QVariant(qreal(3)));
- QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethodNoArgs", "return 7"));
- QTest::qWait(100);
+ QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethodNoArgs", "return 7",
+ &success));
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, rv)));
@@ -434,8 +381,10 @@ void tst_QQmlEngineDebugService::setMethodBody()
Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
QVERIFY(rv == QVariant(qreal(28)));
- QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethod", "return a + 7"));
- QTest::qWait(100);
+ QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethod", "return a + 7",
+ &success));
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
@@ -445,96 +394,78 @@ void tst_QQmlEngineDebugService::setMethodBody()
void tst_QQmlEngineDebugService::watch_property()
{
- QQmlDebugObjectReference obj = findRootObject();
- QQmlDebugPropertyReference prop = findProperty(obj.properties(), "width");
+ QmlDebugObjectReference obj = findRootObject();
+ QmlDebugPropertyReference prop = findProperty(obj.properties, "width");
- QQmlDebugPropertyWatch *watch;
+ bool success;
- QQmlEngineDebug *unconnected = new QQmlEngineDebug(0);
- watch = unconnected->addWatch(prop, this);
- QCOMPARE(watch->state(), QQmlDebugWatch::Dead);
- delete watch;
+ QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
+ unconnected->addWatch(prop, &success);
+ QVERIFY(!success);
delete unconnected;
- watch = m_dbg->addWatch(QQmlDebugPropertyReference(), this);
- QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State))));
- QCOMPARE(watch->state(), QQmlDebugWatch::Inactive);
- delete watch;
+ m_dbg->addWatch(QmlDebugPropertyReference(), &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), false);
- watch = m_dbg->addWatch(prop, this);
- QCOMPARE(watch->state(), QQmlDebugWatch::Waiting);
- QCOMPARE(watch->objectDebugId(), obj.debugId());
- QCOMPARE(watch->name(), prop.name());
+ quint32 id = m_dbg->addWatch(prop, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
- QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));
+ QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)));
int origWidth = m_rootItem->property("width").toInt();
m_rootItem->setProperty("width", origWidth*2);
- // stateChanged() is received before valueChanged()
- QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State))));
- QCOMPARE(watch->state(), QQmlDebugWatch::Active);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
QCOMPARE(spy.count(), 1);
- m_dbg->removeWatch(watch);
- delete watch;
+ m_dbg->removeWatch(id, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
// restore original value and verify spy doesn't get additional signal since watch has been removed
m_rootItem->setProperty("width", origWidth);
QTest::qWait(100);
QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name().toUtf8());
+ QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name.toUtf8());
QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2));
}
void tst_QQmlEngineDebugService::watch_object()
{
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines);
-
- QVERIFY(q_engines->engines().count() > 0);
- QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
- waitForQuery(q_context);
-
- QVERIFY(q_context->rootContext().contexts().count());
- QVERIFY(q_context->rootContext().contexts().last().objects().count() > 0);
- QQmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().contexts().last().objects()[0], this);
- waitForQuery(q_obj);
-
- QQmlDebugObjectReference obj = q_obj->object();
+ QmlDebugObjectReference obj = findRootObject();
- delete q_engines;
- delete q_context;
- delete q_obj;
+ bool success;
- QQmlDebugWatch *watch;
-
- QQmlEngineDebug *unconnected = new QQmlEngineDebug(0);
- watch = unconnected->addWatch(obj, this);
- QCOMPARE(watch->state(), QQmlDebugWatch::Dead);
- delete watch;
+ QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
+ unconnected->addWatch(obj, &success);
+ QVERIFY(!success);
delete unconnected;
- watch = m_dbg->addWatch(QQmlDebugObjectReference(), this);
- QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State))));
- QCOMPARE(watch->state(), QQmlDebugWatch::Inactive);
- delete watch;
+ m_dbg->addWatch(QmlDebugObjectReference(), &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), false);
- watch = m_dbg->addWatch(obj, this);
- QCOMPARE(watch->state(), QQmlDebugWatch::Waiting);
- QCOMPARE(watch->objectDebugId(), obj.debugId());
+ quint32 id = m_dbg->addWatch(obj, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
- QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));
+ QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)));
int origWidth = m_rootItem->property("width").toInt();
int origHeight = m_rootItem->property("height").toInt();
m_rootItem->setProperty("width", origWidth*2);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
m_rootItem->setProperty("height", origHeight*2);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
- // stateChanged() is received before any valueChanged() signals
- QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State))));
- QCOMPARE(watch->state(), QQmlDebugWatch::Active);
QVERIFY(spy.count() > 0);
int newWidth = -1;
@@ -548,8 +479,10 @@ void tst_QQmlEngineDebugService::watch_object()
}
- m_dbg->removeWatch(watch);
- delete watch;
+ m_dbg->removeWatch(id, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
// since watch has been removed, restoring the original values should not trigger a valueChanged()
spy.clear();
@@ -570,58 +503,50 @@ void tst_QQmlEngineDebugService::watch_expression()
int origWidth = m_rootItem->property("width").toInt();
- QQmlDebugObjectReference obj = findRootObject();
+ QmlDebugObjectReference obj = findRootObject();
- QQmlDebugObjectExpressionWatch *watch;
+ bool success;
- QQmlEngineDebug *unconnected = new QQmlEngineDebug(0);
- watch = unconnected->addWatch(obj, expr, this);
- QCOMPARE(watch->state(), QQmlDebugWatch::Dead);
- delete watch;
+ QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
+ unconnected->addWatch(obj, expr, &success);
+ QVERIFY(!success);
delete unconnected;
- watch = m_dbg->addWatch(QQmlDebugObjectReference(), expr, this);
- QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State))));
- QCOMPARE(watch->state(), QQmlDebugWatch::Inactive);
- delete watch;
-
- watch = m_dbg->addWatch(obj, expr, this);
- QCOMPARE(watch->state(), QQmlDebugWatch::Waiting);
- QCOMPARE(watch->objectDebugId(), obj.debugId());
- QCOMPARE(watch->expression(), expr);
+ m_dbg->addWatch(QmlDebugObjectReference(), expr, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), false);
- QSignalSpy spyState(watch, SIGNAL(stateChanged(QQmlDebugWatch::State)));
+ quint32 id = m_dbg->addWatch(obj, expr, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
- QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));
- int expectedSpyCount = incrementCount + 1; // should also get signal with expression's initial value
+ QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)));
int width = origWidth;
for (int i=0; i<incrementCount+1; i++) {
if (i > 0) {
width += increment;
m_rootItem->setProperty("width", width);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
}
- if (!QQmlDebugTest::waitForSignal(watch, SIGNAL(valueChanged(QByteArray,QVariant))))
- QFAIL("Did not receive valueChanged() for expression");
}
- if (spyState.count() == 0)
- QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State))));
- QCOMPARE(spyState.count(), 1);
- QCOMPARE(watch->state(), QQmlDebugWatch::Active);
-
- m_dbg->removeWatch(watch);
- delete watch;
+ m_dbg->removeWatch(id, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
// restore original value and verify spy doesn't get a signal since watch has been removed
m_rootItem->setProperty("width", origWidth);
QTest::qWait(100);
- QCOMPARE(spy.count(), expectedSpyCount);
+ QCOMPARE(spy.count(), incrementCount);
width = origWidth + increment;
for (int i=0; i<spy.count(); i++) {
- QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width);
width += increment;
+ QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width);
}
}
@@ -637,165 +562,126 @@ void tst_QQmlEngineDebugService::watch_expression_data()
void tst_QQmlEngineDebugService::watch_context()
{
- QQmlDebugContextReference c;
- QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebug::addWatch(): Not implemented");
- QVERIFY(!m_dbg->addWatch(c, QString(), this));
+ QmlDebugContextReference c;
+ QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebugClient::addWatch(): Not implemented");
+ bool success;
+ m_dbg->addWatch(c, QString(), &success);
+ QVERIFY(!success);
}
void tst_QQmlEngineDebugService::watch_file()
{
- QQmlDebugFileReference f;
- QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebug::addWatch(): Not implemented");
- QVERIFY(!m_dbg->addWatch(f, this));
+ QmlDebugFileReference f;
+ QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebugClient::addWatch(): Not implemented");
+ bool success;
+ m_dbg->addWatch(f, &success);
+ QVERIFY(!success);
}
void tst_QQmlEngineDebugService::queryAvailableEngines()
{
- QQmlDebugEnginesQuery *q_engines;
+ bool success;
- QQmlEngineDebug *unconnected = new QQmlEngineDebug(0);
- q_engines = unconnected->queryAvailableEngines(0);
- QCOMPARE(q_engines->state(), QQmlDebugQuery::Error);
- delete q_engines;
+ QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
+ unconnected->queryAvailableEngines(&success);
+ QVERIFY(!success);
delete unconnected;
- q_engines = m_dbg->queryAvailableEngines(this);
- delete q_engines;
-
- q_engines = m_dbg->queryAvailableEngines(this);
- QVERIFY(q_engines->engines().isEmpty());
- waitForQuery(q_engines);
+ m_dbg->queryAvailableEngines(&success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
// TODO test multiple engines
- QList<QQmlDebugEngineReference> engines = q_engines->engines();
+ QList<QmlDebugEngineReference> engines = m_dbg->engines();
QCOMPARE(engines.count(), 1);
- foreach(const QQmlDebugEngineReference &e, engines) {
- QCOMPARE(e.debugId(), QQmlDebugService::idForObject(m_engine));
- QCOMPARE(e.name(), m_engine->objectName());
+ foreach (const QmlDebugEngineReference &e, engines) {
+ QCOMPARE(e.debugId, QQmlDebugService::idForObject(m_engine));
+ QCOMPARE(e.name, m_engine->objectName());
}
-
- // Make query invalid by deleting client
- q_engines = m_dbg->queryAvailableEngines(this);
- QCOMPARE(q_engines->state(), QQmlDebugQuery::Waiting);
- delete m_dbg;
- QCOMPARE(q_engines->state(), QQmlDebugQuery::Error);
- delete q_engines;
- m_dbg = new QQmlEngineDebug(m_conn, this);
}
void tst_QQmlEngineDebugService::queryRootContexts()
{
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines);
- int engineId = q_engines->engines()[0].debugId();
- delete q_engines;
-
- QQmlDebugRootContextQuery *q_context;
+ bool success;
+ m_dbg->queryAvailableEngines(&success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QVERIFY(m_dbg->engines().count());
+ int engineId = m_dbg->engines()[0].debugId;
- QQmlEngineDebug *unconnected = new QQmlEngineDebug(0);
- q_context = unconnected->queryRootContexts(engineId, this);
- QCOMPARE(q_context->state(), QQmlDebugQuery::Error);
- delete q_context;
+ QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
+ unconnected->queryRootContexts(engineId, &success);
+ QVERIFY(!success);
delete unconnected;
- q_context = m_dbg->queryRootContexts(engineId, this);
- delete q_context;
-
- q_context = m_dbg->queryRootContexts(engineId, this);
- waitForQuery(q_context);
+ m_dbg->queryRootContexts(engineId, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
QQmlContext *actualContext = m_engine->rootContext();
- QQmlDebugContextReference context = q_context->rootContext();
- QCOMPARE(context.debugId(), QQmlDebugService::idForObject(actualContext));
- QCOMPARE(context.name(), actualContext->objectName());
+ QmlDebugContextReference context = m_dbg->rootContext();
+ QCOMPARE(context.debugId, QQmlDebugService::idForObject(actualContext));
+ QCOMPARE(context.name, actualContext->objectName());
// root context query sends only root object data - it doesn't fill in
// the children or property info
- QCOMPARE(context.objects().count(), 0);
-
- QCOMPARE(context.contexts().count(), 5);
- QVERIFY(context.contexts()[0].debugId() >= 0);
- QCOMPARE(context.contexts()[0].name(), QString("tst_QQmlDebug_childContext"));
-
- // Make query invalid by deleting client
- q_context = m_dbg->queryRootContexts(engineId, this);
- QCOMPARE(q_context->state(), QQmlDebugQuery::Waiting);
- delete m_dbg;
- QCOMPARE(q_context->state(), QQmlDebugQuery::Error);
- delete q_context;
- m_dbg = new QQmlEngineDebug(m_conn, this);
+ QCOMPARE(context.objects.count(), 0);
+ QCOMPARE(context.contexts.count(), 5);
+ QVERIFY(context.contexts[0].debugId >= 0);
+ QCOMPARE(context.contexts[0].name, QString("tst_QQmlDebug_childContext"));
}
void tst_QQmlEngineDebugService::queryObject()
{
QFETCH(bool, recursive);
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines);
+ bool success;
- QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
- waitForQuery(q_context);
- QQmlDebugObjectReference rootObject = q_context->rootContext().contexts().last().objects()[0];
+ QmlDebugObjectReference rootObject = findRootObject();
- QQmlDebugObjectQuery *q_obj = 0;
-
- QQmlEngineDebug *unconnected = new QQmlEngineDebug(0);
- q_obj = recursive ? unconnected->queryObjectRecursive(rootObject, this) : unconnected->queryObject(rootObject, this);
- QCOMPARE(q_obj->state(), QQmlDebugQuery::Error);
- delete q_obj;
+ QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
+ recursive ? unconnected->queryObjectRecursive(rootObject, &success) : unconnected->queryObject(rootObject, &success);
+ QVERIFY(!success);
delete unconnected;
- q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this);
- delete q_obj;
-
- q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this);
- waitForQuery(q_obj);
-
- QQmlDebugObjectReference obj = q_obj->object();
+ recursive ? m_dbg->queryObjectRecursive(rootObject, &success) : m_dbg->queryObject(rootObject, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
- delete q_engines;
- delete q_context;
-
- // Make query invalid by deleting client
- q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this);
- QCOMPARE(q_obj->state(), QQmlDebugQuery::Waiting);
- delete m_dbg;
- QCOMPARE(q_obj->state(), QQmlDebugQuery::Error);
- delete q_obj;
- m_dbg = new QQmlEngineDebug(m_conn, this);
+ QmlDebugObjectReference obj = m_dbg->object();
// check source as defined in main()
- QQmlDebugFileReference source = obj.source();
- QCOMPARE(source.url(), QUrl::fromLocalFile(""));
- QCOMPARE(source.lineNumber(), 3);
- QCOMPARE(source.columnNumber(), 1);
+ QmlDebugFileReference source = obj.source;
+ QCOMPARE(source.url, QUrl::fromLocalFile(""));
+ QCOMPARE(source.lineNumber, 3);
+ QCOMPARE(source.columnNumber, 1);
// generically test all properties, children and childrens' properties
recursiveObjectTest(m_rootItem, obj, recursive);
if (recursive) {
- foreach(const QQmlDebugObjectReference &child, obj.children())
- QVERIFY(child.properties().count() > 0);
+ foreach (const QmlDebugObjectReference &child, obj.children)
+ QVERIFY(child.properties.count() > 0);
- QQmlDebugObjectReference rect;
- QQmlDebugObjectReference text;
- foreach (const QQmlDebugObjectReference &child, obj.children()) {
- if (child.className() == "Rectangle")
+ QmlDebugObjectReference rect;
+ QmlDebugObjectReference text;
+ foreach (const QmlDebugObjectReference &child, obj.children) {
+ if (child.className == "Rectangle")
rect = child;
- else if (child.className() == "Text")
+ else if (child.className == "Text")
text = child;
}
// test specific property values
- QCOMPARE(findProperty(rect.properties(), "width").value(), qVariantFromValue(500));
- QCOMPARE(findProperty(rect.properties(), "height").value(), qVariantFromValue(600));
- QCOMPARE(findProperty(rect.properties(), "color").value(), qVariantFromValue(QColor("blue")));
+ QCOMPARE(findProperty(rect.properties, "width").value, qVariantFromValue(500));
+ QCOMPARE(findProperty(rect.properties, "height").value, qVariantFromValue(600));
+ QCOMPARE(findProperty(rect.properties, "color").value, qVariantFromValue(QColor("blue")));
- QCOMPARE(findProperty(text.properties(), "color").value(), qVariantFromValue(QColor("blue")));
+ QCOMPARE(findProperty(text.properties, "color").value, qVariantFromValue(QColor("blue")));
} else {
- foreach(const QQmlDebugObjectReference &child, obj.children())
- QCOMPARE(child.properties().count(), 0);
+ foreach (const QmlDebugObjectReference &child, obj.children)
+ QCOMPARE(child.properties.count(), 0);
}
}
@@ -812,40 +698,20 @@ void tst_QQmlEngineDebugService::queryExpressionResult()
QFETCH(QString, expr);
QFETCH(QVariant, result);
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines); // check immediate deletion is ok
-
- QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
- waitForQuery(q_context);
- int objectId = q_context->rootContext().contexts().last().objects()[0].debugId();
+ int objectId = findRootObject().debugId;
- QQmlDebugExpressionQuery *q_expr;
+ bool success;
- QQmlEngineDebug *unconnected = new QQmlEngineDebug(0);
- q_expr = unconnected->queryExpressionResult(objectId, expr, this);
- QCOMPARE(q_expr->state(), QQmlDebugQuery::Error);
- delete q_expr;
+ QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
+ unconnected->queryExpressionResult(objectId, expr, &success);
+ QVERIFY(!success);
delete unconnected;
- q_expr = m_dbg->queryExpressionResult(objectId, expr, this);
- delete q_expr;
-
- q_expr = m_dbg->queryExpressionResult(objectId, expr, this);
- QCOMPARE(q_expr->expression().toString(), expr);
- waitForQuery(q_expr);
+ m_dbg->queryExpressionResult(objectId, expr, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
- QCOMPARE(q_expr->result(), result);
-
- delete q_engines;
- delete q_context;
-
- // Make query invalid by deleting client
- q_expr = m_dbg->queryExpressionResult(objectId, expr, this);
- QCOMPARE(q_expr->state(), QQmlDebugQuery::Waiting);
- delete m_dbg;
- QCOMPARE(q_expr->state(), QQmlDebugQuery::Error);
- delete q_expr;
- m_dbg = new QQmlEngineDebug(m_conn, this);
+ QCOMPARE(m_dbg->resultExpr(), result);
}
void tst_QQmlEngineDebugService::queryExpressionResult_data()
@@ -863,204 +729,94 @@ void tst_QQmlEngineDebugService::queryExpressionResult_data()
QTest::newRow("varObjMap") << "varObjMap" << qVariantFromValue(map);
}
-void tst_QQmlEngineDebugService::tst_QQmlDebugFileReference()
-{
- QQmlDebugFileReference ref;
- QVERIFY(ref.url().isEmpty());
- QCOMPARE(ref.lineNumber(), -1);
- QCOMPARE(ref.columnNumber(), -1);
-
- ref.setUrl(QUrl("http://test"));
- QCOMPARE(ref.url(), QUrl("http://test"));
- ref.setLineNumber(1);
- QCOMPARE(ref.lineNumber(), 1);
- ref.setColumnNumber(1);
- QCOMPARE(ref.columnNumber(), 1);
-
- QQmlDebugFileReference copy(ref);
- QQmlDebugFileReference copyAssign;
- copyAssign = ref;
- foreach (const QQmlDebugFileReference &r, (QList<QQmlDebugFileReference>() << copy << copyAssign)) {
- QCOMPARE(r.url(), ref.url());
- QCOMPARE(r.lineNumber(), ref.lineNumber());
- QCOMPARE(r.columnNumber(), ref.columnNumber());
- }
-}
-
-void tst_QQmlEngineDebugService::tst_QQmlDebugEngineReference()
-{
- QQmlDebugEngineReference ref;
- QCOMPARE(ref.debugId(), -1);
- QVERIFY(ref.name().isEmpty());
-
- ref = QQmlDebugEngineReference(1);
- QCOMPARE(ref.debugId(), 1);
- QVERIFY(ref.name().isEmpty());
-
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines);
- ref = q_engines->engines()[0];
- delete q_engines;
-
- QQmlDebugEngineReference copy(ref);
- QQmlDebugEngineReference copyAssign;
- copyAssign = ref;
- foreach (const QQmlDebugEngineReference &r, (QList<QQmlDebugEngineReference>() << copy << copyAssign)) {
- QCOMPARE(r.debugId(), ref.debugId());
- QCOMPARE(r.name(), ref.name());
- }
-}
-
-void tst_QQmlEngineDebugService::tst_QQmlDebugObjectReference()
-{
- QQmlDebugObjectReference ref;
- QCOMPARE(ref.debugId(), -1);
- QCOMPARE(ref.className(), QString());
- QCOMPARE(ref.name(), QString());
- QCOMPARE(ref.contextDebugId(), -1);
- QVERIFY(ref.properties().isEmpty());
- QVERIFY(ref.children().isEmpty());
-
- QQmlDebugFileReference source = ref.source();
- QVERIFY(source.url().isEmpty());
- QVERIFY(source.lineNumber() < 0);
- QVERIFY(source.columnNumber() < 0);
-
- ref = QQmlDebugObjectReference(1);
- QCOMPARE(ref.debugId(), 1);
-
- QQmlDebugObjectReference rootObject = findRootObject();
- QQmlDebugObjectQuery *query = m_dbg->queryObjectRecursive(rootObject, this);
- waitForQuery(query);
- ref = query->object();
- delete query;
-
- QVERIFY(ref.debugId() >= 0);
-
- QQmlDebugObjectReference copy(ref);
- QQmlDebugObjectReference copyAssign;
- copyAssign = ref;
- foreach (const QQmlDebugObjectReference &r, (QList<QQmlDebugObjectReference>() << copy << copyAssign))
- recursiveCompareObjects(r, ref);
-}
-
-void tst_QQmlEngineDebugService::tst_QQmlDebugContextReference()
-{
- QQmlDebugContextReference ref;
- QCOMPARE(ref.debugId(), -1);
- QVERIFY(ref.name().isEmpty());
- QVERIFY(ref.objects().isEmpty());
- QVERIFY(ref.contexts().isEmpty());
-
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines);
- QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
- waitForQuery(q_context);
-
- ref = q_context->rootContext();
- delete q_engines;
- delete q_context;
- QVERIFY(ref.debugId() >= 0);
-
- QQmlDebugContextReference copy(ref);
- QQmlDebugContextReference copyAssign;
- copyAssign = ref;
- foreach (const QQmlDebugContextReference &r, (QList<QQmlDebugContextReference>() << copy << copyAssign))
- recursiveCompareContexts(r, ref);
-}
-
-void tst_QQmlEngineDebugService::tst_QQmlDebugPropertyReference()
-{
- QQmlDebugObjectReference rootObject = findRootObject();
- QQmlDebugObjectQuery *query = m_dbg->queryObject(rootObject, this);
- waitForQuery(query);
- QQmlDebugObjectReference obj = query->object();
- delete query;
-
- QQmlDebugPropertyReference ref = findProperty(obj.properties(), "scale");
- QVERIFY(ref.objectDebugId() > 0);
- QVERIFY(!ref.name().isEmpty());
- QVERIFY(!ref.value().isNull());
- QVERIFY(!ref.valueTypeName().isEmpty());
- QVERIFY(!ref.binding().isEmpty());
- QVERIFY(ref.hasNotifySignal());
-
- QQmlDebugPropertyReference copy(ref);
- QQmlDebugPropertyReference copyAssign;
- copyAssign = ref;
- foreach (const QQmlDebugPropertyReference &r, (QList<QQmlDebugPropertyReference>() << copy << copyAssign))
- compareProperties(r, ref);
-}
-
void tst_QQmlEngineDebugService::setBindingForObject()
{
- QQmlDebugObjectReference rootObject = findRootObject();
- QVERIFY(rootObject.debugId() != -1);
- QQmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties(), "width");
+ QmlDebugObjectReference rootObject = findRootObject();
+ QVERIFY(rootObject.debugId != -1);
+ QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width");
- QCOMPARE(widthPropertyRef.value(), QVariant(10));
- QCOMPARE(widthPropertyRef.binding(), QString());
+ QCOMPARE(widthPropertyRef.value, QVariant(10));
+ QCOMPARE(widthPropertyRef.binding, QString());
+ bool success;
//
// set literal
//
- m_dbg->setBindingForObject(rootObject.debugId(), "width", "15", true);
+ m_dbg->setBindingForObject(rootObject.debugId, "width", "15", true,
+ QString(), -1, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
rootObject = findRootObject();
- widthPropertyRef = findProperty(rootObject.properties(), "width");
+ widthPropertyRef = findProperty(rootObject.properties, "width");
- QCOMPARE(widthPropertyRef.value(), QVariant(15));
- QCOMPARE(widthPropertyRef.binding(), QString());
+ QCOMPARE(widthPropertyRef.value, QVariant(15));
+ QCOMPARE(widthPropertyRef.binding, QString());
//
// set expression
//
- m_dbg->setBindingForObject(rootObject.debugId(), "width", "height", false);
+ m_dbg->setBindingForObject(rootObject.debugId, "width", "height", false,
+ QString(), -1, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
rootObject = findRootObject();
- widthPropertyRef = findProperty(rootObject.properties(), "width");
+ widthPropertyRef = findProperty(rootObject.properties, "width");
- QCOMPARE(widthPropertyRef.value(), QVariant(20));
- QCOMPARE(widthPropertyRef.binding(), QString("height"));
+ QCOMPARE(widthPropertyRef.value, QVariant(20));
+ QCOMPARE(widthPropertyRef.binding, QString("height"));
//
// reset
//
- m_dbg->resetBindingForObject(rootObject.debugId(), "width");
+ m_dbg->resetBindingForObject(rootObject.debugId, "width", &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
rootObject = findRootObject();
- widthPropertyRef = findProperty(rootObject.properties(), "width");
+ widthPropertyRef = findProperty(rootObject.properties, "width");
// QCOMPARE(widthPropertyRef.value(), QVariant(0)); // TODO: Shouldn't this work?
- QCOMPARE(widthPropertyRef.binding(), QString());
+ QCOMPARE(widthPropertyRef.binding, QString());
//
// set handler
//
rootObject = findRootObject();
- QCOMPARE(rootObject.children().size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement
- QQmlDebugObjectReference mouseAreaObject = rootObject.children().at(2);
- QQmlDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(mouseAreaObject, this);
- waitForQuery(q_obj);
- mouseAreaObject = q_obj->object();
+ QCOMPARE(rootObject.children.size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement
+ QmlDebugObjectReference mouseAreaObject = rootObject.children.at(2);
+ m_dbg->queryObjectRecursive(mouseAreaObject, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ mouseAreaObject = m_dbg->object();
- QCOMPARE(mouseAreaObject.className(), QString("MouseArea"));
+ QCOMPARE(mouseAreaObject.className, QString("MouseArea"));
- QQmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties(), "onEntered");
+ QmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered");
- QCOMPARE(onEnteredRef.name(), QString("onEntered"));
- QCOMPARE(onEnteredRef.value(), QVariant("(function onEntered() { { console.log('hello') } })"));
+ QCOMPARE(onEnteredRef.name, QString("onEntered"));
+ QCOMPARE(onEnteredRef.value, QVariant("(function onEntered() { { console.log('hello') } })"));
- m_dbg->setBindingForObject(mouseAreaObject.debugId(), "onEntered", "{console.log('hello, world') }", false) ;
+ m_dbg->setBindingForObject(mouseAreaObject.debugId, "onEntered",
+ "{console.log('hello, world') }", false,
+ QString(), -1, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
rootObject = findRootObject();
- mouseAreaObject = rootObject.children().at(2);
- q_obj = m_dbg->queryObjectRecursive(mouseAreaObject, this);
- waitForQuery(q_obj);
- mouseAreaObject = q_obj->object();
- onEnteredRef = findProperty(mouseAreaObject.properties(), "onEntered");
- QCOMPARE(onEnteredRef.name(), QString("onEntered"));
- QCOMPARE(onEnteredRef.value(), QVariant("{console.log('hello, world') }"));
+ mouseAreaObject = rootObject.children.at(2);
+ m_dbg->queryObjectRecursive(mouseAreaObject, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ mouseAreaObject = m_dbg->object();
+ onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered");
+ QCOMPARE(onEnteredRef.name, QString("onEntered"));
+ QCOMPARE(onEnteredRef.value, QVariant("{console.log('hello, world') }"));
}
void tst_QQmlEngineDebugService::setBindingInStates()
@@ -1069,155 +825,151 @@ void tst_QQmlEngineDebugService::setBindingInStates()
const int sourceIndex = 3;
- QQmlDebugObjectReference obj = findRootObject(sourceIndex);
-
- QVERIFY(obj.debugId() != -1);
- QVERIFY(obj.children().count() >= 2);
+ QmlDebugObjectReference obj = findRootObject(sourceIndex);
+ QVERIFY(obj.debugId != -1);
+ QVERIFY(obj.children.count() >= 2);
+ bool success;
// We are going to switch state a couple of times, we need to get rid of the transition before
- QQmlDebugExpressionQuery *q_deleteTransition = m_dbg->queryExpressionResult(obj.debugId(),QString("transitions = []"),this);
- waitForQuery(q_deleteTransition);
- delete q_deleteTransition;
+ m_dbg->queryExpressionResult(obj.debugId,QString("transitions = []"), &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
// check initial value of the property that is changing
- QQmlDebugExpressionQuery *q_setState;
- q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this);
- waitForQuery(q_setState);
- delete q_setState;
+ m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),200);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(),200);
- q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this);
- waitForQuery(q_setState);
- delete q_setState;
+ m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""),
+ &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
obj = findRootObject(sourceIndex, true);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100);
// change the binding
- QQmlDebugObjectReference state = obj.children()[1];
- QCOMPARE(state.className(), QString("State"));
- QVERIFY(state.children().count() > 0);
+ QmlDebugObjectReference state = obj.children[1];
+ QCOMPARE(state.className, QString("State"));
+ QVERIFY(state.children.count() > 0);
- QQmlDebugObjectReference propertyChange = state.children()[0];
- QVERIFY(propertyChange.debugId() != -1);
+ QmlDebugObjectReference propertyChange = state.children[0];
+ QVERIFY(propertyChange.debugId != -1);
- QVERIFY( m_dbg->setBindingForObject(propertyChange.debugId(), "width",QVariant(300),true) );
+ m_dbg->setBindingForObject(propertyChange.debugId, "width",QVariant(300),true,
+ QString(), -1, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
// check properties changed in state
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100);
- q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this);
- waitForQuery(q_setState);
- delete q_setState;
+ m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300);
// check changing properties of base state from within a state
- QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"width","height*2",false));
- QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"height","200",true));
+ m_dbg->setBindingForObject(obj.debugId,"width","height*2",false,
+ QString(), -1, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ m_dbg->setBindingForObject(obj.debugId,"height","200",true,
+ QString(), -1, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300);
- q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this);
- waitForQuery(q_setState);
- delete q_setState;
+ m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""), &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400);
// reset binding while in a state
- q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this);
- waitForQuery(q_setState);
- delete q_setState;
+ m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300);
- m_dbg->resetBindingForObject(propertyChange.debugId(), "width");
+ m_dbg->resetBindingForObject(propertyChange.debugId, "width", &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400);
// re-add binding
- m_dbg->setBindingForObject(propertyChange.debugId(), "width", "300", true);
+ m_dbg->setBindingForObject(propertyChange.debugId, "width", "300", true,
+ QString(), -1, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+ QCOMPARE(m_dbg->valid(), true);
obj = findRootObject(sourceIndex);
- QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300);
+ QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300);
}
void tst_QQmlEngineDebugService::queryObjectTree()
{
const int sourceIndex = 3;
- // Check if states/transitions are initialized when fetching root item
- QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
- waitForQuery(q_engines);
-
- QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
- waitForQuery(q_context);
-
- QVERIFY(q_context->rootContext().contexts().count() >= sourceIndex);
- int count = q_context->rootContext().contexts().count();
- QQmlDebugObjectReference rootObject = q_context->rootContext().contexts()[count - sourceIndex - 1].objects()[0];
-
- QQmlDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(rootObject, this);
- waitForQuery(q_obj);
-
- QQmlDebugObjectReference obj = q_obj->object();
-
- delete q_engines;
- delete q_context;
- delete q_obj;
-
- QVERIFY(obj.debugId() != -1);
- QVERIFY(obj.children().count() >= 2);
-
+ QmlDebugObjectReference obj = findRootObject(sourceIndex, true);
+ QVERIFY(obj.debugId != -1);
+ QVERIFY(obj.children.count() >= 2);
// check state
- QQmlDebugObjectReference state = obj.children()[1];
- QCOMPARE(state.className(), QString("State"));
- QVERIFY(state.children().count() > 0);
+ QmlDebugObjectReference state = obj.children[1];
+ QCOMPARE(state.className, QString("State"));
+ QVERIFY(state.children.count() > 0);
- QQmlDebugObjectReference propertyChange = state.children()[0];
- QVERIFY(propertyChange.debugId() != -1);
+ QmlDebugObjectReference propertyChange = state.children[0];
+ QVERIFY(propertyChange.debugId != -1);
- QQmlDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties(),"target");
- QCOMPARE(propertyChangeTarget.objectDebugId(), propertyChange.debugId());
+ QmlDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties,"target");
+ QCOMPARE(propertyChangeTarget.objectDebugId, propertyChange.debugId);
- QQmlDebugObjectReference targetReference = qvariant_cast<QQmlDebugObjectReference>(propertyChangeTarget.value());
- QVERIFY(targetReference.debugId() != -1);
+ QmlDebugObjectReference targetReference = qvariant_cast<QmlDebugObjectReference>(propertyChangeTarget.value);
+ QVERIFY(targetReference.debugId != -1);
// check transition
- QQmlDebugObjectReference transition = obj.children()[0];
- QCOMPARE(transition.className(), QString("Transition"));
- QCOMPARE(findProperty(transition.properties(),"from").value().toString(), QString("*"));
- QCOMPARE(findProperty(transition.properties(),"to").value(), findProperty(state.properties(),"name").value());
- QVERIFY(transition.children().count() > 0);
+ QmlDebugObjectReference transition = obj.children[0];
+ QCOMPARE(transition.className, QString("Transition"));
+ QCOMPARE(findProperty(transition.properties,"from").value.toString(), QString("*"));
+ QCOMPARE(findProperty(transition.properties,"to").value, findProperty(state.properties,"name").value);
+ QVERIFY(transition.children.count() > 0);
- QQmlDebugObjectReference animation = transition.children()[0];
- QVERIFY(animation.debugId() != -1);
+ QmlDebugObjectReference animation = transition.children[0];
+ QVERIFY(animation.debugId != -1);
- QQmlDebugPropertyReference animationTarget = findProperty(animation.properties(),"target");
- QCOMPARE(animationTarget.objectDebugId(), animation.debugId());
+ QmlDebugPropertyReference animationTarget = findProperty(animation.properties,"target");
+ QCOMPARE(animationTarget.objectDebugId, animation.debugId);
- targetReference = qvariant_cast<QQmlDebugObjectReference>(animationTarget.value());
- QVERIFY(targetReference.debugId() != -1);
+ targetReference = qvariant_cast<QmlDebugObjectReference>(animationTarget.value);
+ QVERIFY(targetReference.debugId != -1);
- QCOMPARE(findProperty(animation.properties(),"property").value().toString(), QString("width"));
- QCOMPARE(findProperty(animation.properties(),"duration").value().toInt(), 100);
+ QCOMPARE(findProperty(animation.properties,"property").value.toString(), QString("width"));
+ QCOMPARE(findProperty(animation.properties,"duration").value.toInt(), 100);
}
int main(int argc, char *argv[])
diff --git a/tests/auto/qml/debugger/qqmlinspector/app/app.pro b/tests/auto/qml/debugger/qqmlinspector/app/app.pro
index 9c7574a97e..ce8bfc645a 100644
--- a/tests/auto/qml/debugger/qqmlinspector/app/app.pro
+++ b/tests/auto/qml/debugger/qqmlinspector/app/app.pro
@@ -1,4 +1,5 @@
TARGET = app
+DESTDIR = $$OUT_PWD
QT += qml quick
CONFIG += declarative_debug
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
index e30b847139..39e0f0d3e5 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
@@ -141,7 +141,11 @@ void tst_QQmlInspector::cleanupTestCase()
void tst_QQmlInspector::init()
{
+#if defined(Q_OS_WIN)
+ const QString executable = "app\\app.exe";
+#else
const QString executable = "app/app";
+#endif
const QString argument = "-qmljsdebugger=port:"STR_PORT",block";
m_process = new QQmlDebugProcess(executable);
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro
index b4ca60b547..6d4758182e 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro
@@ -9,4 +9,4 @@ include(../shared/debugutil.pri)
CONFIG += parallel_test declarative_debug
-QT += qml-private testlib
+QT += qml testlib
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
index 2bf43c92a2..a83590cf63 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
@@ -12,4 +12,4 @@ OTHER_FILES += data/test.qml
CONFIG += parallel_test declarative_debug
-QT += core-private v8-private qml-private testlib
+QT += core qml testlib
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 2b33ab3944..972c3ac6f4 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -42,7 +42,6 @@
#include <qtest.h>
#include <QLibraryInfo>
-#include "QtQml/private/qqmlprofilerservice_p.h"
#include "debugutil_p.h"
#include "qqmldebugclient.h"
#include "../../../shared/util.h"
@@ -50,11 +49,59 @@
#define PORT 13773
#define STR_PORT "13773"
+struct QQmlProfilerData
+{
+ qint64 time;
+ int messageType;
+ int detailType;
+
+ //###
+ QString detailData; //used by RangeData and RangeLocation
+ int line; //used by RangeLocation
+ int column; //used by RangeLocation
+ int framerate; //used by animation events
+ int animationcount; //used by animation events
+
+ QByteArray toByteArray() const;
+};
+
class QQmlProfilerClient : public QQmlDebugClient
{
Q_OBJECT
public:
+ enum Message {
+ Event,
+ RangeStart,
+ RangeData,
+ RangeLocation,
+ RangeEnd,
+ Complete, // end of transmission
+
+ MaximumMessage
+ };
+
+ enum EventType {
+ FramePaint,
+ Mouse,
+ Key,
+ AnimationFrame,
+ EndTrace,
+ StartTrace,
+
+ MaximumEventType
+ };
+
+ enum RangeType {
+ Painting,
+ Compiling,
+ Creating,
+ Binding, //running a binding
+ HandlingSignal, //running a signal handler
+
+ MaximumRangeType
+ };
+
QQmlProfilerClient(QQmlDebugConnection *connection)
: QQmlDebugClient(QLatin1String("CanvasFrameRate"), connection)
{
@@ -123,21 +170,21 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message)
QVERIFY(data.time >= -1);
switch (data.messageType) {
- case (QQmlProfilerService::Event): {
+ case (QQmlProfilerClient::Event): {
stream >> data.detailType;
switch (data.detailType) {
- case QQmlProfilerService::AnimationFrame: {
+ case QQmlProfilerClient::AnimationFrame: {
stream >> data.framerate >> data.animationcount;
QVERIFY(data.framerate != -1);
QVERIFY(data.animationcount != -1);
break;
}
- case QQmlProfilerService::FramePaint:
- case QQmlProfilerService::Mouse:
- case QQmlProfilerService::Key:
- case QQmlProfilerService::StartTrace:
- case QQmlProfilerService::EndTrace:
+ case QQmlProfilerClient::FramePaint:
+ case QQmlProfilerClient::Mouse:
+ case QQmlProfilerClient::Key:
+ case QQmlProfilerClient::StartTrace:
+ case QQmlProfilerClient::EndTrace:
break;
default: {
QString failMsg = QString("Unknown event type:") + data.detailType;
@@ -147,28 +194,28 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message)
}
break;
}
- case QQmlProfilerService::Complete: {
+ case QQmlProfilerClient::Complete: {
emit complete();
return;
}
- case QQmlProfilerService::RangeStart: {
+ case QQmlProfilerClient::RangeStart: {
stream >> data.detailType;
- QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType);
+ QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType);
break;
}
- case QQmlProfilerService::RangeEnd: {
+ case QQmlProfilerClient::RangeEnd: {
stream >> data.detailType;
- QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType);
+ QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType);
break;
}
- case QQmlProfilerService::RangeData: {
+ case QQmlProfilerClient::RangeData: {
stream >> data.detailType >> data.detailData;
- QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType);
+ QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType);
break;
}
- case QQmlProfilerService::RangeLocation: {
+ case QQmlProfilerClient::RangeLocation: {
stream >> data.detailType >> data.detailData >> data.line >> data.column;
- QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType);
+ QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType);
QVERIFY(data.line >= -2);
break;
}
@@ -229,12 +276,12 @@ void tst_QQmlProfilerService::blockingConnectWithTraceEnabled()
QVERIFY(m_client->traceMessages.count());
// must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace);
+ QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
// must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace);
+ QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
void tst_QQmlProfilerService::blockingConnectWithTraceDisabled()
@@ -254,12 +301,12 @@ void tst_QQmlProfilerService::blockingConnectWithTraceDisabled()
QVERIFY(m_client->traceMessages.count());
// must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace);
+ QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
// must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace);
+ QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
void tst_QQmlProfilerService::nonBlockingConnect()
@@ -276,12 +323,12 @@ void tst_QQmlProfilerService::nonBlockingConnect()
}
// must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace);
+ QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
// must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace);
+ QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
void tst_QQmlProfilerService::profileOnExit()
@@ -298,12 +345,12 @@ void tst_QQmlProfilerService::profileOnExit()
}
// must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace);
+ QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
// must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace);
+ QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
QTEST_MAIN(tst_QQmlProfilerService)
diff --git a/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro b/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro
index a8dd634855..5088953c92 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro
+++ b/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro
@@ -12,4 +12,4 @@ OTHER_FILES += data/test.qml
CONFIG += parallel_test declarative_debug
-QT += qml-private testlib
+QT += qml testlib
diff --git a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
index 7b9cda937c..497d544390 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
+++ b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
@@ -42,7 +42,6 @@
#include <qtest.h>
#include <QLibraryInfo>
-#include "QtQml/private/qv8profilerservice_p.h"
#include "debugutil_p.h"
#include "qqmldebugclient.h"
#include "../../../shared/util.h"
@@ -50,11 +49,34 @@
#define PORT 13774
#define STR_PORT "13774"
+struct QV8ProfilerData
+{
+ int messageType;
+ QString filename;
+ QString functionname;
+ int lineNumber;
+ double totalTime;
+ double selfTime;
+ int treeLevel;
+
+ QByteArray toByteArray() const;
+};
+
class QV8ProfilerClient : public QQmlDebugClient
{
Q_OBJECT
public:
+ enum MessageType {
+ V8Entry,
+ V8Complete,
+ V8SnapshotChunk,
+ V8SnapshotComplete,
+ V8Started,
+
+ V8MaximumMessage
+ };
+
QV8ProfilerClient(QQmlDebugConnection *connection)
: QQmlDebugClient(QLatin1String("V8Profiler"), connection)
{
@@ -139,28 +161,28 @@ void QV8ProfilerClient::messageReceived(const QByteArray &message)
stream >> messageType;
QVERIFY(messageType >= 0);
- QVERIFY(messageType < QV8ProfilerService::V8MaximumMessage);
+ QVERIFY(messageType < QV8ProfilerClient::V8MaximumMessage);
switch (messageType) {
- case QV8ProfilerService::V8Entry: {
+ case QV8ProfilerClient::V8Entry: {
QV8ProfilerData entry;
stream >> entry.filename >> entry.functionname >> entry.lineNumber >> entry.totalTime >> entry.selfTime >> entry.treeLevel;
traceMessages.append(entry);
break;
}
- case QV8ProfilerService::V8Complete:
+ case QV8ProfilerClient::V8Complete:
emit complete();
break;
- case QV8ProfilerService::V8SnapshotChunk: {
+ case QV8ProfilerClient::V8SnapshotChunk: {
QByteArray json;
stream >> json;
snapshotMessages.append(json);
break;
}
- case QV8ProfilerService::V8SnapshotComplete:
+ case QV8ProfilerClient::V8SnapshotComplete:
emit snapshot();
break;
- case QV8ProfilerService::V8Started:
+ case QV8ProfilerClient::V8Started:
emit started();
break;
default:
diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp
index 3d2f460456..ac9fa5fae2 100644
--- a/tests/auto/qml/debugger/shared/debugutil.cpp
+++ b/tests/auto/qml/debugger/shared/debugutil.cpp
@@ -55,23 +55,6 @@ bool QQmlDebugTest::waitForSignal(QObject *receiver, const char *member, int tim
return timer.isActive();
}
-QQmlDebugTestService::QQmlDebugTestService(const QString &s, float version, QObject *parent)
- : QQmlDebugService(s, version, parent)
-{
- registerService();
-}
-
-void QQmlDebugTestService::messageReceived(const QByteArray &ba)
-{
- sendMessage(ba);
-}
-
-void QQmlDebugTestService::stateChanged(State)
-{
- emit stateHasChanged();
-}
-
-
QQmlDebugTestClient::QQmlDebugTestClient(const QString &s, QQmlDebugConnection *c)
: QQmlDebugClient(s, c)
{
diff --git a/tests/auto/qml/debugger/shared/debugutil.pri b/tests/auto/qml/debugger/shared/debugutil.pri
index b74f6b08b0..cb9c761395 100644
--- a/tests/auto/qml/debugger/shared/debugutil.pri
+++ b/tests/auto/qml/debugger/shared/debugutil.pri
@@ -1,9 +1,8 @@
-QT += core-private
-
HEADERS += $$PWD/debugutil_p.h \
$$PWD/qqmldebugclient.h \
- $$PWD/qqmlenginedebug_p.h
+ $$PWD/../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h
+
SOURCES += $$PWD/debugutil.cpp \
$$PWD/qqmldebugclient.cpp \
- $$PWD/qqmlenginedebug.cpp
+ $$PWD/../../../../../src/plugins/qmltooling/shared/qpacketprotocol.cpp
diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h
index 177c712833..2ea295b822 100644
--- a/tests/auto/qml/debugger/shared/debugutil_p.h
+++ b/tests/auto/qml/debugger/shared/debugutil_p.h
@@ -52,7 +52,6 @@
#include <QtQml/qqmlengine.h>
#include "qqmldebugclient.h"
-#include <private/qqmldebugservice_p.h>
class QQmlDebugTest
{
@@ -60,20 +59,6 @@ public:
static bool waitForSignal(QObject *receiver, const char *member, int timeout = 5000);
};
-class QQmlDebugTestService : public QQmlDebugService
-{
- Q_OBJECT
-public:
- QQmlDebugTestService(const QString &s, float version = 1, QObject *parent = 0);
-
-signals:
- void stateHasChanged();
-
-protected:
- virtual void messageReceived(const QByteArray &ba);
- virtual void stateChanged(State state);
-};
-
class QQmlDebugTestClient : public QQmlDebugClient
{
Q_OBJECT
diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
index 0453f88350..50feb950fb 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
@@ -40,8 +40,7 @@
****************************************************************************/
#include "qqmldebugclient.h"
-
-#include <private/qpacketprotocol_p.h>
+#include "../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h"
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.h b/tests/auto/qml/debugger/shared/qqmldebugclient.h
index 1b05e86a64..0f140a1db1 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugclient.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugclient.h
@@ -44,8 +44,6 @@
#include <QtNetwork/qtcpsocket.h>
-#include <private/qtqmlglobal_p.h>
-
class QQmlDebugConnectionPrivate;
class QQmlDebugConnection : public QIODevice
{
@@ -84,7 +82,6 @@ class QQmlDebugClientPrivate;
class QQmlDebugClient : public QObject
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlDebugClient)
Q_DISABLE_COPY(QQmlDebugClient)
public:
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
new file mode 100644
index 0000000000..1c8afd836b
--- /dev/null
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugtestservice.h"
+
+QQmlDebugTestService::QQmlDebugTestService(const QString &s, float version, QObject *parent)
+ : QQmlDebugService(s, version, parent)
+{
+ registerService();
+}
+
+void QQmlDebugTestService::messageReceived(const QByteArray &ba)
+{
+ sendMessage(ba);
+}
+
+void QQmlDebugTestService::stateChanged(State)
+{
+ emit stateHasChanged();
+}
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
new file mode 100644
index 0000000000..14fda551de
--- /dev/null
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
@@ -0,0 +1,62 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGTESTSERVICE_H
+#define QQMLDEBUGTESTSERVICE_H
+
+#include <private/qqmldebugservice_p.h>
+
+class QQmlDebugTestService : public QQmlDebugService
+{
+ Q_OBJECT
+public:
+ QQmlDebugTestService(const QString &s, float version = 1, QObject *parent = 0);
+
+signals:
+ void stateHasChanged();
+
+protected:
+ virtual void messageReceived(const QByteArray &ba);
+ virtual void stateChanged(State state);
+};
+
+#endif // QQMLDEBUGTESTSERVICE_H
diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebug.cpp b/tests/auto/qml/debugger/shared/qqmlenginedebug.cpp
deleted file mode 100644
index 8a46c7617c..0000000000
--- a/tests/auto/qml/debugger/shared/qqmlenginedebug.cpp
+++ /dev/null
@@ -1,1068 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlenginedebug_p.h"
-
-#include "qqmldebugclient.h"
-
-#include <private/qqmlenginedebugservice_p.h>
-
-#include <QtCore/private/qobject_p.h>
-
-class QQmlEngineDebugClient : public QQmlDebugClient
-{
-public:
- QQmlEngineDebugClient(QQmlDebugConnection *client, QQmlEngineDebugPrivate *p);
-
-protected:
- virtual void stateChanged(State state);
- virtual void messageReceived(const QByteArray &);
-
-private:
- QQmlEngineDebugPrivate *priv;
- friend class QQmlEngineDebugPrivate;
-};
-
-class QQmlEngineDebugPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlEngineDebug)
-public:
- QQmlEngineDebugPrivate(QQmlDebugConnection *);
- ~QQmlEngineDebugPrivate();
-
- void stateChanged(QQmlEngineDebug::State status);
- void message(const QByteArray &);
-
- QQmlEngineDebugClient *client;
- int nextId;
- int getId();
-
- void decode(QDataStream &, QQmlDebugContextReference &);
- void decode(QDataStream &, QQmlDebugObjectReference &, bool simple);
-
- static void remove(QQmlEngineDebug *, QQmlDebugEnginesQuery *);
- static void remove(QQmlEngineDebug *, QQmlDebugRootContextQuery *);
- static void remove(QQmlEngineDebug *, QQmlDebugObjectQuery *);
- static void remove(QQmlEngineDebug *, QQmlDebugExpressionQuery *);
- static void remove(QQmlEngineDebug *, QQmlDebugWatch *);
-
- QHash<int, QQmlDebugEnginesQuery *> enginesQuery;
- QHash<int, QQmlDebugRootContextQuery *> rootContextQuery;
- QHash<int, QQmlDebugObjectQuery *> objectQuery;
- QHash<int, QQmlDebugExpressionQuery *> expressionQuery;
-
- QHash<int, QQmlDebugWatch *> watched;
-};
-
-QQmlEngineDebugClient::QQmlEngineDebugClient(QQmlDebugConnection *client,
- QQmlEngineDebugPrivate *p)
- : QQmlDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p)
-{
-}
-
-void QQmlEngineDebugClient::stateChanged(State status)
-{
- if (priv)
- priv->stateChanged(static_cast<QQmlEngineDebug::State>(status));
-}
-
-void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
-{
- if (priv)
- priv->message(data);
-}
-
-QQmlEngineDebugPrivate::QQmlEngineDebugPrivate(QQmlDebugConnection *c)
- : client(new QQmlEngineDebugClient(c, this)), nextId(0)
-{
-}
-
-QQmlEngineDebugPrivate::~QQmlEngineDebugPrivate()
-{
- if (client)
- client->priv = 0;
- delete client;
-
- QHash<int, QQmlDebugEnginesQuery*>::iterator enginesIter = enginesQuery.begin();
- for (; enginesIter != enginesQuery.end(); ++enginesIter) {
- enginesIter.value()->m_client = 0;
- if (enginesIter.value()->state() == QQmlDebugQuery::Waiting)
- enginesIter.value()->setState(QQmlDebugQuery::Error);
- }
-
- QHash<int, QQmlDebugRootContextQuery*>::iterator rootContextIter = rootContextQuery.begin();
- for (; rootContextIter != rootContextQuery.end(); ++rootContextIter) {
- rootContextIter.value()->m_client = 0;
- if (rootContextIter.value()->state() == QQmlDebugQuery::Waiting)
- rootContextIter.value()->setState(QQmlDebugQuery::Error);
- }
-
- QHash<int, QQmlDebugObjectQuery*>::iterator objectIter = objectQuery.begin();
- for (; objectIter != objectQuery.end(); ++objectIter) {
- objectIter.value()->m_client = 0;
- if (objectIter.value()->state() == QQmlDebugQuery::Waiting)
- objectIter.value()->setState(QQmlDebugQuery::Error);
- }
-
- QHash<int, QQmlDebugExpressionQuery*>::iterator exprIter = expressionQuery.begin();
- for (; exprIter != expressionQuery.end(); ++exprIter) {
- exprIter.value()->m_client = 0;
- if (exprIter.value()->state() == QQmlDebugQuery::Waiting)
- exprIter.value()->setState(QQmlDebugQuery::Error);
- }
-
- QHash<int, QQmlDebugWatch*>::iterator watchIter = watched.begin();
- for (; watchIter != watched.end(); ++watchIter) {
- watchIter.value()->m_client = 0;
- watchIter.value()->setState(QQmlDebugWatch::Dead);
- }
-}
-
-int QQmlEngineDebugPrivate::getId()
-{
- return nextId++;
-}
-
-void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugEnginesQuery *q)
-{
- if (c && q) {
- QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c);
- p->enginesQuery.remove(q->m_queryId);
- }
-}
-
-void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c,
- QQmlDebugRootContextQuery *q)
-{
- if (c && q) {
- QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c);
- p->rootContextQuery.remove(q->m_queryId);
- }
-}
-
-void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugObjectQuery *q)
-{
- if (c && q) {
- QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c);
- p->objectQuery.remove(q->m_queryId);
- }
-}
-
-void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugExpressionQuery *q)
-{
- if (c && q) {
- QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c);
- p->expressionQuery.remove(q->m_queryId);
- }
-}
-
-void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugWatch *w)
-{
- if (c && w) {
- QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c);
- p->watched.remove(w->m_queryId);
- }
-}
-
-void QQmlEngineDebugPrivate::decode(QDataStream &ds, QQmlDebugObjectReference &o,
- bool simple)
-{
- QQmlEngineDebugService::QQmlObjectData data;
- ds >> data;
- o.m_debugId = data.objectId;
- o.m_class = data.objectType;
- o.m_idString = data.idString;
- o.m_name = data.objectName;
- o.m_source.m_url = data.url;
- o.m_source.m_lineNumber = data.lineNumber;
- o.m_source.m_columnNumber = data.columnNumber;
- o.m_contextDebugId = data.contextId;
-
- if (simple)
- return;
-
- int childCount;
- bool recur;
- ds >> childCount >> recur;
-
- for (int ii = 0; ii < childCount; ++ii) {
- o.m_children.append(QQmlDebugObjectReference());
- decode(ds, o.m_children.last(), !recur);
- }
-
- int propCount;
- ds >> propCount;
-
- for (int ii = 0; ii < propCount; ++ii) {
- QQmlEngineDebugService::QQmlObjectProperty data;
- ds >> data;
- QQmlDebugPropertyReference prop;
- prop.m_objectDebugId = o.m_debugId;
- prop.m_name = data.name;
- prop.m_binding = data.binding;
- prop.m_hasNotifySignal = data.hasNotifySignal;
- prop.m_valueTypeName = data.valueTypeName;
- switch (data.type) {
- case QQmlEngineDebugService::QQmlObjectProperty::Basic:
- case QQmlEngineDebugService::QQmlObjectProperty::List:
- case QQmlEngineDebugService::QQmlObjectProperty::SignalProperty:
- {
- prop.m_value = data.value;
- break;
- }
- case QQmlEngineDebugService::QQmlObjectProperty::Object:
- {
- QQmlDebugObjectReference obj;
- obj.m_debugId = prop.m_value.toInt();
- prop.m_value = QVariant::fromValue(obj);
- break;
- }
- case QQmlEngineDebugService::QQmlObjectProperty::Unknown:
- break;
- }
- o.m_properties << prop;
- }
-}
-
-void QQmlEngineDebugPrivate::decode(QDataStream &ds, QQmlDebugContextReference &c)
-{
- ds >> c.m_name >> c.m_debugId;
-
- int contextCount;
- ds >> contextCount;
-
- for (int ii = 0; ii < contextCount; ++ii) {
- c.m_contexts.append(QQmlDebugContextReference());
- decode(ds, c.m_contexts.last());
- }
-
- int objectCount;
- ds >> objectCount;
-
- for (int ii = 0; ii < objectCount; ++ii) {
- QQmlDebugObjectReference obj;
- decode(ds, obj, true);
-
- obj.m_contextDebugId = c.m_debugId;
- c.m_objects << obj;
- }
-}
-
-void QQmlEngineDebugPrivate::stateChanged(QQmlEngineDebug::State status)
-{
- emit q_func()->stateChanged(status);
-}
-
-void QQmlEngineDebugPrivate::message(const QByteArray &data)
-{
- QDataStream ds(data);
-
- QByteArray type;
- ds >> type;
-
- //qDebug() << "QQmlEngineDebugPrivate::message()" << type;
-
- if (type == "LIST_ENGINES_R") {
- int queryId;
- ds >> queryId;
-
- QQmlDebugEnginesQuery *query = enginesQuery.value(queryId);
- if (!query)
- return;
- enginesQuery.remove(queryId);
-
- int count;
- ds >> count;
-
- for (int ii = 0; ii < count; ++ii) {
- QQmlDebugEngineReference ref;
- ds >> ref.m_name;
- ds >> ref.m_debugId;
- query->m_engines << ref;
- }
-
- query->m_client = 0;
- query->setState(QQmlDebugQuery::Completed);
- } else if (type == "LIST_OBJECTS_R") {
- int queryId;
- ds >> queryId;
-
- QQmlDebugRootContextQuery *query = rootContextQuery.value(queryId);
- if (!query)
- return;
- rootContextQuery.remove(queryId);
-
- if (!ds.atEnd())
- decode(ds, query->m_context);
-
- query->m_client = 0;
- query->setState(QQmlDebugQuery::Completed);
- } else if (type == "FETCH_OBJECT_R") {
- int queryId;
- ds >> queryId;
-
- QQmlDebugObjectQuery *query = objectQuery.value(queryId);
- if (!query)
- return;
- objectQuery.remove(queryId);
-
- if (!ds.atEnd())
- decode(ds, query->m_object, false);
-
- query->m_client = 0;
- query->setState(QQmlDebugQuery::Completed);
- } else if (type == "EVAL_EXPRESSION_R") {
- int queryId;
- QVariant result;
- ds >> queryId >> result;
-
- QQmlDebugExpressionQuery *query = expressionQuery.value(queryId);
- if (!query)
- return;
- expressionQuery.remove(queryId);
-
- query->m_result = result;
- query->m_client = 0;
- query->setState(QQmlDebugQuery::Completed);
- } else if (type == "WATCH_PROPERTY_R") {
- int queryId;
- bool ok;
- ds >> queryId >> ok;
-
- QQmlDebugWatch *watch = watched.value(queryId);
- if (!watch)
- return;
-
- watch->setState(ok ? QQmlDebugWatch::Active : QQmlDebugWatch::Inactive);
- } else if (type == "WATCH_OBJECT_R") {
- int queryId;
- bool ok;
- ds >> queryId >> ok;
-
- QQmlDebugWatch *watch = watched.value(queryId);
- if (!watch)
- return;
-
- watch->setState(ok ? QQmlDebugWatch::Active : QQmlDebugWatch::Inactive);
- } else if (type == "WATCH_EXPR_OBJECT_R") {
- int queryId;
- bool ok;
- ds >> queryId >> ok;
-
- QQmlDebugWatch *watch = watched.value(queryId);
- if (!watch)
- return;
-
- watch->setState(ok ? QQmlDebugWatch::Active : QQmlDebugWatch::Inactive);
- } else if (type == "UPDATE_WATCH") {
- int queryId;
- int debugId;
- QByteArray name;
- QVariant value;
- ds >> queryId >> debugId >> name >> value;
-
- QQmlDebugWatch *watch = watched.value(queryId, 0);
- if (!watch)
- return;
- emit watch->valueChanged(name, value);
- } else if (type == "OBJECT_CREATED") {
- emit q_func()->newObjects();
- }
-}
-
-QQmlEngineDebug::QQmlEngineDebug(QQmlDebugConnection *client, QObject *parent)
- : QObject(*(new QQmlEngineDebugPrivate(client)), parent)
-{
-}
-
-QQmlEngineDebug::~QQmlEngineDebug()
-{
-}
-
-QQmlEngineDebug::State QQmlEngineDebug::state() const
-{
- Q_D(const QQmlEngineDebug);
-
- return static_cast<QQmlEngineDebug::State>(d->client->state());
-}
-
-QQmlDebugPropertyWatch *QQmlEngineDebug::addWatch(const QQmlDebugPropertyReference &property, QObject *parent)
-{
- Q_D(QQmlEngineDebug);
-
- QQmlDebugPropertyWatch *watch = new QQmlDebugPropertyWatch(parent);
- if (d->client->state() == QQmlDebugClient::Enabled) {
- int queryId = d->getId();
- watch->m_queryId = queryId;
- watch->m_client = this;
- watch->m_objectDebugId = property.objectDebugId();
- watch->m_name = property.name();
- d->watched.insert(queryId, watch);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toUtf8();
- d->client->sendMessage(message);
- } else {
- watch->m_state = QQmlDebugWatch::Dead;
- }
-
- return watch;
-}
-
-QQmlDebugWatch *QQmlEngineDebug::addWatch(const QQmlDebugContextReference &, const QString &, QObject *)
-{
- qWarning("QQmlEngineDebug::addWatch(): Not implemented");
- return 0;
-}
-
-QQmlDebugObjectExpressionWatch *QQmlEngineDebug::addWatch(const QQmlDebugObjectReference &object, const QString &expr, QObject *parent)
-{
- Q_D(QQmlEngineDebug);
- QQmlDebugObjectExpressionWatch *watch = new QQmlDebugObjectExpressionWatch(parent);
- if (d->client->state() == QQmlDebugClient::Enabled) {
- int queryId = d->getId();
- watch->m_queryId = queryId;
- watch->m_client = this;
- watch->m_objectDebugId = object.debugId();
- watch->m_expr = expr;
- d->watched.insert(queryId, watch);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("WATCH_EXPR_OBJECT") << queryId << object.debugId() << expr;
- d->client->sendMessage(message);
- } else {
- watch->m_state = QQmlDebugWatch::Dead;
- }
- return watch;
-}
-
-QQmlDebugWatch *QQmlEngineDebug::addWatch(const QQmlDebugObjectReference &object, QObject *parent)
-{
- Q_D(QQmlEngineDebug);
-
- QQmlDebugWatch *watch = new QQmlDebugWatch(parent);
- if (d->client->state() == QQmlDebugClient::Enabled) {
- int queryId = d->getId();
- watch->m_queryId = queryId;
- watch->m_client = this;
- watch->m_objectDebugId = object.debugId();
- d->watched.insert(queryId, watch);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("WATCH_OBJECT") << queryId << object.debugId();
- d->client->sendMessage(message);
- } else {
- watch->m_state = QQmlDebugWatch::Dead;
- }
-
- return watch;
-}
-
-QQmlDebugWatch *QQmlEngineDebug::addWatch(const QQmlDebugFileReference &, QObject *)
-{
- qWarning("QQmlEngineDebug::addWatch(): Not implemented");
- return 0;
-}
-
-void QQmlEngineDebug::removeWatch(QQmlDebugWatch *watch)
-{
- Q_D(QQmlEngineDebug);
-
- if (!watch || !watch->m_client)
- return;
-
- watch->m_client = 0;
- watch->setState(QQmlDebugWatch::Inactive);
-
- d->watched.remove(watch->queryId());
-
- if (d->client && d->client->state() == QQmlDebugClient::Enabled) {
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("NO_WATCH") << watch->queryId();
- d->client->sendMessage(message);
- }
-}
-
-QQmlDebugEnginesQuery *QQmlEngineDebug::queryAvailableEngines(QObject *parent)
-{
- Q_D(QQmlEngineDebug);
-
- QQmlDebugEnginesQuery *query = new QQmlDebugEnginesQuery(parent);
- if (d->client->state() == QQmlDebugClient::Enabled) {
- query->m_client = this;
- int queryId = d->getId();
- query->m_queryId = queryId;
- d->enginesQuery.insert(queryId, query);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("LIST_ENGINES") << queryId;
- d->client->sendMessage(message);
- } else {
- query->m_state = QQmlDebugQuery::Error;
- }
-
- return query;
-}
-
-QQmlDebugRootContextQuery *QQmlEngineDebug::queryRootContexts(const QQmlDebugEngineReference &engine, QObject *parent)
-{
- Q_D(QQmlEngineDebug);
-
- QQmlDebugRootContextQuery *query = new QQmlDebugRootContextQuery(parent);
- if (d->client->state() == QQmlDebugClient::Enabled && engine.debugId() != -1) {
- query->m_client = this;
- int queryId = d->getId();
- query->m_queryId = queryId;
- d->rootContextQuery.insert(queryId, query);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("LIST_OBJECTS") << queryId << engine.debugId();
- d->client->sendMessage(message);
- } else {
- query->m_state = QQmlDebugQuery::Error;
- }
-
- return query;
-}
-
-QQmlDebugObjectQuery *QQmlEngineDebug::queryObject(const QQmlDebugObjectReference &object, QObject *parent)
-{
- Q_D(QQmlEngineDebug);
-
- QQmlDebugObjectQuery *query = new QQmlDebugObjectQuery(parent);
- if (d->client->state() == QQmlDebugClient::Enabled && object.debugId() != -1) {
- query->m_client = this;
- int queryId = d->getId();
- query->m_queryId = queryId;
- d->objectQuery.insert(queryId, query);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
- << false << true;
- d->client->sendMessage(message);
- } else {
- query->m_state = QQmlDebugQuery::Error;
- }
-
- return query;
-}
-
-QQmlDebugObjectQuery *QQmlEngineDebug::queryObjectRecursive(const QQmlDebugObjectReference &object, QObject *parent)
-{
- Q_D(QQmlEngineDebug);
-
- QQmlDebugObjectQuery *query = new QQmlDebugObjectQuery(parent);
- if (d->client->state() == QQmlDebugClient::Enabled && object.debugId() != -1) {
- query->m_client = this;
- int queryId = d->getId();
- query->m_queryId = queryId;
- d->objectQuery.insert(queryId, query);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
- << true << true;
- d->client->sendMessage(message);
- } else {
- query->m_state = QQmlDebugQuery::Error;
- }
-
- return query;
-}
-
-QQmlDebugExpressionQuery *QQmlEngineDebug::queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent)
-{
- Q_D(QQmlEngineDebug);
-
- QQmlDebugExpressionQuery *query = new QQmlDebugExpressionQuery(parent);
- if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
- query->m_client = this;
- query->m_expr = expr;
- int queryId = d->getId();
- query->m_queryId = queryId;
- d->expressionQuery.insert(queryId, query);
-
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("EVAL_EXPRESSION") << queryId << objectDebugId << expr;
- d->client->sendMessage(message);
- } else {
- query->m_state = QQmlDebugQuery::Error;
- }
-
- return query;
-}
-
-bool QQmlEngineDebug::setBindingForObject(int objectDebugId, const QString &propertyName,
- const QVariant &bindingExpression,
- bool isLiteralValue,
- QString source, int line)
-{
- Q_D(QQmlEngineDebug);
-
- if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("SET_BINDING") << objectDebugId << propertyName << bindingExpression << isLiteralValue << source << line;
- d->client->sendMessage(message);
- return true;
- } else {
- return false;
- }
-}
-
-bool QQmlEngineDebug::resetBindingForObject(int objectDebugId, const QString &propertyName)
-{
- Q_D(QQmlEngineDebug);
-
- if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName;
- d->client->sendMessage(message);
- return true;
- } else {
- return false;
- }
-}
-
-bool QQmlEngineDebug::setMethodBody(int objectDebugId, const QString &methodName,
- const QString &methodBody)
-{
- Q_D(QQmlEngineDebug);
-
- if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("SET_METHOD_BODY") << objectDebugId << methodName << methodBody;
- d->client->sendMessage(message);
- return true;
- } else {
- return false;
- }
-}
-
-QQmlDebugWatch::QQmlDebugWatch(QObject *parent)
- : QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1)
-{
-}
-
-QQmlDebugWatch::~QQmlDebugWatch()
-{
- if (m_client && m_queryId != -1)
- QQmlEngineDebugPrivate::remove(m_client, this);
-}
-
-int QQmlDebugWatch::queryId() const
-{
- return m_queryId;
-}
-
-int QQmlDebugWatch::objectDebugId() const
-{
- return m_objectDebugId;
-}
-
-QQmlDebugWatch::State QQmlDebugWatch::state() const
-{
- return m_state;
-}
-
-void QQmlDebugWatch::setState(State s)
-{
- if (m_state == s)
- return;
- m_state = s;
- emit stateChanged(m_state);
-}
-
-QQmlDebugPropertyWatch::QQmlDebugPropertyWatch(QObject *parent)
- : QQmlDebugWatch(parent)
-{
-}
-
-QString QQmlDebugPropertyWatch::name() const
-{
- return m_name;
-}
-
-
-QQmlDebugObjectExpressionWatch::QQmlDebugObjectExpressionWatch(QObject *parent)
- : QQmlDebugWatch(parent)
-{
-}
-
-QString QQmlDebugObjectExpressionWatch::expression() const
-{
- return m_expr;
-}
-
-
-QQmlDebugQuery::QQmlDebugQuery(QObject *parent)
- : QObject(parent), m_state(Waiting)
-{
-}
-
-QQmlDebugQuery::State QQmlDebugQuery::state() const
-{
- return m_state;
-}
-
-bool QQmlDebugQuery::isWaiting() const
-{
- return m_state == Waiting;
-}
-
-void QQmlDebugQuery::setState(State s)
-{
- if (m_state == s)
- return;
- m_state = s;
- emit stateChanged(m_state);
-}
-
-QQmlDebugEnginesQuery::QQmlDebugEnginesQuery(QObject *parent)
- : QQmlDebugQuery(parent), m_client(0), m_queryId(-1)
-{
-}
-
-QQmlDebugEnginesQuery::~QQmlDebugEnginesQuery()
-{
- if (m_client && m_queryId != -1)
- QQmlEngineDebugPrivate::remove(m_client, this);
-}
-
-QList<QQmlDebugEngineReference> QQmlDebugEnginesQuery::engines() const
-{
- return m_engines;
-}
-
-QQmlDebugRootContextQuery::QQmlDebugRootContextQuery(QObject *parent)
- : QQmlDebugQuery(parent), m_client(0), m_queryId(-1)
-{
-}
-
-QQmlDebugRootContextQuery::~QQmlDebugRootContextQuery()
-{
- if (m_client && m_queryId != -1)
- QQmlEngineDebugPrivate::remove(m_client, this);
-}
-
-QQmlDebugContextReference QQmlDebugRootContextQuery::rootContext() const
-{
- return m_context;
-}
-
-QQmlDebugObjectQuery::QQmlDebugObjectQuery(QObject *parent)
- : QQmlDebugQuery(parent), m_client(0), m_queryId(-1)
-{
-}
-
-QQmlDebugObjectQuery::~QQmlDebugObjectQuery()
-{
- if (m_client && m_queryId != -1)
- QQmlEngineDebugPrivate::remove(m_client, this);
-}
-
-QQmlDebugObjectReference QQmlDebugObjectQuery::object() const
-{
- return m_object;
-}
-
-QQmlDebugExpressionQuery::QQmlDebugExpressionQuery(QObject *parent)
- : QQmlDebugQuery(parent), m_client(0), m_queryId(-1)
-{
-}
-
-QQmlDebugExpressionQuery::~QQmlDebugExpressionQuery()
-{
- if (m_client && m_queryId != -1)
- QQmlEngineDebugPrivate::remove(m_client, this);
-}
-
-QVariant QQmlDebugExpressionQuery::expression() const
-{
- return m_expr;
-}
-
-QVariant QQmlDebugExpressionQuery::result() const
-{
- return m_result;
-}
-
-QQmlDebugEngineReference::QQmlDebugEngineReference()
- : m_debugId(-1)
-{
-}
-
-QQmlDebugEngineReference::QQmlDebugEngineReference(int debugId)
- : m_debugId(debugId)
-{
-}
-
-QQmlDebugEngineReference::QQmlDebugEngineReference(const QQmlDebugEngineReference &o)
- : m_debugId(o.m_debugId), m_name(o.m_name)
-{
-}
-
-QQmlDebugEngineReference &
-QQmlDebugEngineReference::operator=(const QQmlDebugEngineReference &o)
-{
- m_debugId = o.m_debugId; m_name = o.m_name;
- return *this;
-}
-
-int QQmlDebugEngineReference::debugId() const
-{
- return m_debugId;
-}
-
-QString QQmlDebugEngineReference::name() const
-{
- return m_name;
-}
-
-QQmlDebugObjectReference::QQmlDebugObjectReference()
- : m_debugId(-1), m_contextDebugId(-1)
-{
-}
-
-QQmlDebugObjectReference::QQmlDebugObjectReference(int debugId)
- : m_debugId(debugId), m_contextDebugId(-1)
-{
-}
-
-QQmlDebugObjectReference::QQmlDebugObjectReference(const QQmlDebugObjectReference &o)
- : m_debugId(o.m_debugId), m_class(o.m_class), m_idString(o.m_idString),
- m_name(o.m_name), m_source(o.m_source), m_contextDebugId(o.m_contextDebugId),
- m_properties(o.m_properties), m_children(o.m_children)
-{
-}
-
-QQmlDebugObjectReference &
-QQmlDebugObjectReference::operator=(const QQmlDebugObjectReference &o)
-{
- m_debugId = o.m_debugId; m_class = o.m_class; m_idString = o.m_idString;
- m_name = o.m_name; m_source = o.m_source; m_contextDebugId = o.m_contextDebugId;
- m_properties = o.m_properties; m_children = o.m_children;
- return *this;
-}
-
-int QQmlDebugObjectReference::debugId() const
-{
- return m_debugId;
-}
-
-QString QQmlDebugObjectReference::className() const
-{
- return m_class;
-}
-
-QString QQmlDebugObjectReference::idString() const
-{
- return m_idString;
-}
-
-QString QQmlDebugObjectReference::name() const
-{
- return m_name;
-}
-
-QQmlDebugFileReference QQmlDebugObjectReference::source() const
-{
- return m_source;
-}
-
-int QQmlDebugObjectReference::contextDebugId() const
-{
- return m_contextDebugId;
-}
-
-QList<QQmlDebugPropertyReference> QQmlDebugObjectReference::properties() const
-{
- return m_properties;
-}
-
-QList<QQmlDebugObjectReference> QQmlDebugObjectReference::children() const
-{
- return m_children;
-}
-
-QQmlDebugContextReference::QQmlDebugContextReference()
- : m_debugId(-1)
-{
-}
-
-QQmlDebugContextReference::QQmlDebugContextReference(const QQmlDebugContextReference &o)
- : m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts)
-{
-}
-
-QQmlDebugContextReference &QQmlDebugContextReference::operator=(const QQmlDebugContextReference &o)
-{
- m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects;
- m_contexts = o.m_contexts;
- return *this;
-}
-
-int QQmlDebugContextReference::debugId() const
-{
- return m_debugId;
-}
-
-QString QQmlDebugContextReference::name() const
-{
- return m_name;
-}
-
-QList<QQmlDebugObjectReference> QQmlDebugContextReference::objects() const
-{
- return m_objects;
-}
-
-QList<QQmlDebugContextReference> QQmlDebugContextReference::contexts() const
-{
- return m_contexts;
-}
-
-QQmlDebugFileReference::QQmlDebugFileReference()
- : m_lineNumber(-1), m_columnNumber(-1)
-{
-}
-
-QQmlDebugFileReference::QQmlDebugFileReference(const QQmlDebugFileReference &o)
- : m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber)
-{
-}
-
-QQmlDebugFileReference &QQmlDebugFileReference::operator=(const QQmlDebugFileReference &o)
-{
- m_url = o.m_url; m_lineNumber = o.m_lineNumber; m_columnNumber = o.m_columnNumber;
- return *this;
-}
-
-QUrl QQmlDebugFileReference::url() const
-{
- return m_url;
-}
-
-void QQmlDebugFileReference::setUrl(const QUrl &u)
-{
- m_url = u;
-}
-
-int QQmlDebugFileReference::lineNumber() const
-{
- return m_lineNumber;
-}
-
-void QQmlDebugFileReference::setLineNumber(int l)
-{
- m_lineNumber = l;
-}
-
-int QQmlDebugFileReference::columnNumber() const
-{
- return m_columnNumber;
-}
-
-void QQmlDebugFileReference::setColumnNumber(int c)
-{
- m_columnNumber = c;
-}
-
-QQmlDebugPropertyReference::QQmlDebugPropertyReference()
- : m_objectDebugId(-1), m_hasNotifySignal(false)
-{
-}
-
-QQmlDebugPropertyReference::QQmlDebugPropertyReference(const QQmlDebugPropertyReference &o)
- : m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value),
- m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding),
- m_hasNotifySignal(o.m_hasNotifySignal)
-{
-}
-
-QQmlDebugPropertyReference &QQmlDebugPropertyReference::operator=(const QQmlDebugPropertyReference &o)
-{
- m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value;
- m_valueTypeName = o.m_valueTypeName; m_binding = o.m_binding;
- m_hasNotifySignal = o.m_hasNotifySignal;
- return *this;
-}
-
-int QQmlDebugPropertyReference::objectDebugId() const
-{
- return m_objectDebugId;
-}
-
-QString QQmlDebugPropertyReference::name() const
-{
- return m_name;
-}
-
-QString QQmlDebugPropertyReference::valueTypeName() const
-{
- return m_valueTypeName;
-}
-
-QVariant QQmlDebugPropertyReference::value() const
-{
- return m_value;
-}
-
-QString QQmlDebugPropertyReference::binding() const
-{
- return m_binding;
-}
-
-bool QQmlDebugPropertyReference::hasNotifySignal() const
-{
- return m_hasNotifySignal;
-}
-
diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h b/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h
deleted file mode 100644
index 2ebdebca53..0000000000
--- a/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLENGINEDEBUG_H
-#define QQMLENGINEDEBUG_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qobject.h>
-#include <QtCore/qurl.h>
-#include <QtCore/qvariant.h>
-
-#include <private/qtqmlglobal_p.h>
-
-class QQmlDebugConnection;
-class QQmlDebugWatch;
-class QQmlDebugPropertyWatch;
-class QQmlDebugObjectExpressionWatch;
-class QQmlDebugEnginesQuery;
-class QQmlDebugRootContextQuery;
-class QQmlDebugObjectQuery;
-class QQmlDebugExpressionQuery;
-class QQmlDebugPropertyReference;
-class QQmlDebugContextReference;
-class QQmlDebugObjectReference;
-class QQmlDebugFileReference;
-class QQmlDebugEngineReference;
-class QQmlEngineDebugPrivate;
-class QQmlEngineDebug : public QObject
-{
- Q_OBJECT
-public:
- enum State { NotConnected, Unavailable, Enabled };
-
- explicit QQmlEngineDebug(QQmlDebugConnection *, QObject * = 0);
- ~QQmlEngineDebug();
-
- State state() const;
-
- QQmlDebugPropertyWatch *addWatch(const QQmlDebugPropertyReference &,
- QObject *parent = 0);
- QQmlDebugWatch *addWatch(const QQmlDebugContextReference &, const QString &,
- QObject *parent = 0);
- QQmlDebugObjectExpressionWatch *addWatch(const QQmlDebugObjectReference &, const QString &,
- QObject *parent = 0);
- QQmlDebugWatch *addWatch(const QQmlDebugObjectReference &,
- QObject *parent = 0);
- QQmlDebugWatch *addWatch(const QQmlDebugFileReference &,
- QObject *parent = 0);
-
- void removeWatch(QQmlDebugWatch *watch);
-
- QQmlDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0);
- QQmlDebugRootContextQuery *queryRootContexts(const QQmlDebugEngineReference &,
- QObject *parent = 0);
- QQmlDebugObjectQuery *queryObject(const QQmlDebugObjectReference &,
- QObject *parent = 0);
- QQmlDebugObjectQuery *queryObjectRecursive(const QQmlDebugObjectReference &,
- QObject *parent = 0);
- QQmlDebugExpressionQuery *queryExpressionResult(int objectDebugId,
- const QString &expr,
- QObject *parent = 0);
- bool setBindingForObject(int objectDebugId, const QString &propertyName,
- const QVariant &bindingExpression, bool isLiteralValue,
- QString source = QString(), int line = -1);
- bool resetBindingForObject(int objectDebugId, const QString &propertyName);
- bool setMethodBody(int objectDebugId, const QString &methodName, const QString &methodBody);
-
-Q_SIGNALS:
- void newObjects();
- void stateChanged(State state);
-
-private:
- Q_DECLARE_PRIVATE(QQmlEngineDebug)
-};
-
-class QQmlDebugWatch : public QObject
-{
- Q_OBJECT
-public:
- enum State { Waiting, Active, Inactive, Dead };
-
- QQmlDebugWatch(QObject *);
- ~QQmlDebugWatch();
-
- int queryId() const;
- int objectDebugId() const;
- State state() const;
-
-Q_SIGNALS:
- void stateChanged(QQmlDebugWatch::State);
- //void objectChanged(int, const QQmlDebugObjectReference &);
- //void valueChanged(int, const QVariant &);
-
- // Server sends value as string if it is a user-type variant
- void valueChanged(const QByteArray &name, const QVariant &value);
-
-private:
- friend class QQmlEngineDebug;
- friend class QQmlEngineDebugPrivate;
- void setState(State);
- State m_state;
- int m_queryId;
- QQmlEngineDebug *m_client;
- int m_objectDebugId;
-};
-
-class QQmlDebugPropertyWatch : public QQmlDebugWatch
-{
- Q_OBJECT
-public:
- QQmlDebugPropertyWatch(QObject *parent);
-
- QString name() const;
-
-private:
- friend class QQmlEngineDebug;
- QString m_name;
-};
-
-class QQmlDebugObjectExpressionWatch : public QQmlDebugWatch
-{
- Q_OBJECT
-public:
- QQmlDebugObjectExpressionWatch(QObject *parent);
-
- QString expression() const;
-
-private:
- friend class QQmlEngineDebug;
- QString m_expr;
- int m_debugId;
-};
-
-
-class QQmlDebugQuery : public QObject
-{
- Q_OBJECT
-public:
- enum State { Waiting, Error, Completed };
-
- State state() const;
- bool isWaiting() const;
-
-Q_SIGNALS:
- void stateChanged(QQmlDebugQuery::State);
-
-protected:
- QQmlDebugQuery(QObject *);
-
-private:
- friend class QQmlEngineDebug;
- friend class QQmlEngineDebugPrivate;
- void setState(State);
- State m_state;
-};
-
-class QQmlDebugFileReference
-{
-public:
- QQmlDebugFileReference();
- QQmlDebugFileReference(const QQmlDebugFileReference &);
- QQmlDebugFileReference &operator=(const QQmlDebugFileReference &);
-
- QUrl url() const;
- void setUrl(const QUrl &);
- int lineNumber() const;
- void setLineNumber(int);
- int columnNumber() const;
- void setColumnNumber(int);
-
-private:
- friend class QQmlEngineDebugPrivate;
- QUrl m_url;
- int m_lineNumber;
- int m_columnNumber;
-};
-
-class QQmlDebugEngineReference
-{
-public:
- QQmlDebugEngineReference();
- QQmlDebugEngineReference(int);
- QQmlDebugEngineReference(const QQmlDebugEngineReference &);
- QQmlDebugEngineReference &operator=(const QQmlDebugEngineReference &);
-
- int debugId() const;
- QString name() const;
-
-private:
- friend class QQmlEngineDebugPrivate;
- int m_debugId;
- QString m_name;
-};
-
-class QQmlDebugObjectReference
-{
-public:
- QQmlDebugObjectReference();
- QQmlDebugObjectReference(int);
- QQmlDebugObjectReference(const QQmlDebugObjectReference &);
- QQmlDebugObjectReference &operator=(const QQmlDebugObjectReference &);
-
- int debugId() const;
- QString className() const;
- QString idString() const;
- QString name() const;
-
- QQmlDebugFileReference source() const;
- int contextDebugId() const;
-
- QList<QQmlDebugPropertyReference> properties() const;
- QList<QQmlDebugObjectReference> children() const;
-
-private:
- friend class QQmlEngineDebugPrivate;
- int m_debugId;
- QString m_class;
- QString m_idString;
- QString m_name;
- QQmlDebugFileReference m_source;
- int m_contextDebugId;
- QList<QQmlDebugPropertyReference> m_properties;
- QList<QQmlDebugObjectReference> m_children;
-};
-
-class QQmlDebugContextReference
-{
-public:
- QQmlDebugContextReference();
- QQmlDebugContextReference(const QQmlDebugContextReference &);
- QQmlDebugContextReference &operator=(const QQmlDebugContextReference &);
-
- int debugId() const;
- QString name() const;
-
- QList<QQmlDebugObjectReference> objects() const;
- QList<QQmlDebugContextReference> contexts() const;
-
-private:
- friend class QQmlEngineDebugPrivate;
- int m_debugId;
- QString m_name;
- QList<QQmlDebugObjectReference> m_objects;
- QList<QQmlDebugContextReference> m_contexts;
-};
-
-class QQmlDebugPropertyReference
-{
-public:
- QQmlDebugPropertyReference();
- QQmlDebugPropertyReference(const QQmlDebugPropertyReference &);
- QQmlDebugPropertyReference &operator=(const QQmlDebugPropertyReference &);
-
- int objectDebugId() const;
- QString name() const;
- QVariant value() const;
- QString valueTypeName() const;
- QString binding() const;
- bool hasNotifySignal() const;
-
-private:
- friend class QQmlEngineDebugPrivate;
- int m_objectDebugId;
- QString m_name;
- QVariant m_value;
- QString m_valueTypeName;
- QString m_binding;
- bool m_hasNotifySignal;
-};
-
-
-class QQmlDebugEnginesQuery : public QQmlDebugQuery
-{
- Q_OBJECT
-public:
- virtual ~QQmlDebugEnginesQuery();
- QList<QQmlDebugEngineReference> engines() const;
-private:
- friend class QQmlEngineDebug;
- friend class QQmlEngineDebugPrivate;
- QQmlDebugEnginesQuery(QObject *);
- QQmlEngineDebug *m_client;
- int m_queryId;
- QList<QQmlDebugEngineReference> m_engines;
-};
-
-class QQmlDebugRootContextQuery : public QQmlDebugQuery
-{
- Q_OBJECT
-public:
- virtual ~QQmlDebugRootContextQuery();
- QQmlDebugContextReference rootContext() const;
-private:
- friend class QQmlEngineDebug;
- friend class QQmlEngineDebugPrivate;
- QQmlDebugRootContextQuery(QObject *);
- QQmlEngineDebug *m_client;
- int m_queryId;
- QQmlDebugContextReference m_context;
-};
-
-class QQmlDebugObjectQuery : public QQmlDebugQuery
-{
- Q_OBJECT
-public:
- virtual ~QQmlDebugObjectQuery();
- QQmlDebugObjectReference object() const;
-private:
- friend class QQmlEngineDebug;
- friend class QQmlEngineDebugPrivate;
- QQmlDebugObjectQuery(QObject *);
- QQmlEngineDebug *m_client;
- int m_queryId;
- QQmlDebugObjectReference m_object;
-
-};
-
-class QQmlDebugExpressionQuery : public QQmlDebugQuery
-{
- Q_OBJECT
-public:
- virtual ~QQmlDebugExpressionQuery();
- QVariant expression() const;
- QVariant result() const;
-private:
- friend class QQmlEngineDebug;
- friend class QQmlEngineDebugPrivate;
- QQmlDebugExpressionQuery(QObject *);
- QQmlEngineDebug *m_client;
- int m_queryId;
- QVariant m_expr;
- QVariant m_result;
-};
-
-Q_DECLARE_METATYPE(QQmlDebugEngineReference)
-Q_DECLARE_METATYPE(QQmlDebugObjectReference)
-Q_DECLARE_METATYPE(QQmlDebugContextReference)
-Q_DECLARE_METATYPE(QQmlDebugPropertyReference)
-
-#endif // QQMLENGINEDEBUG_H
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 6f9cc93757..e34304b258 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -2369,6 +2369,8 @@ void tst_QJSEngine::valueConversion_basic()
QCOMPARE(eng.fromScriptValue<QChar>(code), c);
QCOMPARE(eng.fromScriptValue<QChar>(eng.toScriptValue(c)), c);
}
+
+ QVERIFY(eng.toScriptValue(static_cast<void *>(0)).isNull());
}
#if 0 // FIXME: No API for custom types
@@ -2588,6 +2590,8 @@ void tst_QJSEngine::valueConversion_QVariant()
}
QCOMPARE(qjsvalue_cast<QVariant>(QJSValue(123)), QVariant(123));
+
+ QVERIFY(eng.toScriptValue(QVariant(QMetaType::VoidStar, 0)).isNull());
}
#if 0 // FIXME: No support for custom types
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index ad655217ad..3522f22ca2 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -993,8 +993,8 @@ void tst_QJSValue::toVariant()
QCOMPARE(qjsvalue_cast<QVariant>(undefined), QVariant());
QJSValue null = eng.evaluate("null");
- QCOMPARE(null.toVariant(), QVariant());
- QCOMPARE(qjsvalue_cast<QVariant>(null), QVariant());
+ QCOMPARE(null.toVariant(), QVariant(QMetaType::VoidStar, 0));
+ QCOMPARE(qjsvalue_cast<QVariant>(null), QVariant(QMetaType::VoidStar, 0));
{
QJSValue number = eng.toScriptValue(123.0);
@@ -1064,6 +1064,14 @@ void tst_QJSValue::toVariant()
QJSValue str = QJSValue(QString("ciao"));
QCOMPARE(str.toVariant(), QVariant(QString("ciao")));
QCOMPARE(qjsvalue_cast<QVariant>(str), QVariant(QString("ciao")));
+
+ QJSValue undef = QJSValue(QJSValue::UndefinedValue);
+ QCOMPARE(undef.toVariant(), QVariant());
+ QCOMPARE(qjsvalue_cast<QVariant>(undef), QVariant());
+
+ QJSValue nil = QJSValue(QJSValue::NullValue);
+ QCOMPARE(nil.toVariant(), QVariant(QMetaType::VoidStar, 0));
+ QCOMPARE(qjsvalue_cast<QVariant>(nil), QVariant(QMetaType::VoidStar, 0));
}
#if 0 // FIXME: No automatic sequence conversion
diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml
new file mode 100644
index 0000000000..578701844c
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyTypeObject {
+ dateProperty: if(1) new Date("1982-11-25")
+ dateTimeProperty: if(1) new Date("2009-05-12T13:22:01")
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml
new file mode 100644
index 0000000000..32b88d0183
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyTypeObject {
+ dateProperty: if(1) "1982-11-25Z"
+ dateTimeProperty: if(1) "2009-05-12T13:22:01Z"
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml
new file mode 100644
index 0000000000..16213c691f
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyTypeObject {
+ dateProperty: if(1) new Date("1982-11-25Z")
+ dateTimeProperty: if(1) new Date("2009-05-12T13:22:01Z")
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml
new file mode 100644
index 0000000000..ff1d85fbef
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyTypeObject {
+ dateProperty: if(1) "1982-11-25Z"
+ dateTimeProperty: if(1) "2009-05-12T15:22:01+02:00"
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml
new file mode 100644
index 0000000000..859c02f79c
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyTypeObject {
+ dateProperty: if(1) new Date("1982-11-25")
+ dateTimeProperty: if(1) new Date("2009-05-12T15:22:01+02:00")
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.qml
new file mode 100644
index 0000000000..07a638d50f
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignDate.qml
@@ -0,0 +1,9 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date("1982-11-25")
+ dateTimeProperty = new Date("2009-05-12T13:22:01")
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/componentCreation.qml b/tests/auto/qml/qqmlecmascript/data/componentCreation.qml
new file mode 100644
index 0000000000..d21301ea13
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/componentCreation.qml
@@ -0,0 +1,52 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject{
+ id: obj
+ objectName: "obj"
+
+ function url()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml');
+ }
+
+ function urlMode()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous);
+ }
+
+ function urlParent()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', obj);
+ }
+
+ function urlNullParent()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', null);
+ }
+
+ function urlModeParent()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, obj);
+ }
+
+ function urlModeNullParent()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, null);
+ }
+
+ function invalidSecondArg()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', 'Bad argument');
+ }
+
+ function invalidThirdArg()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, 'Bad argument');
+ }
+
+ function invalidMode()
+ {
+ obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', -666);
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/enums.3.qml b/tests/auto/qml/qqmlecmascript/data/enums.3.qml
new file mode 100644
index 0000000000..c77d635a1e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/enums.3.qml
@@ -0,0 +1,41 @@
+import QtQuick 2.0
+import Qt.test 1.0
+import Qt.test 1.0 as Namespace
+
+Item {
+ // Enums from type
+ property int a: Item.Center
+ property int b: Item.Right
+
+ // Enums from Qt
+ property int c: Qt.blue
+ property int d: Qt.darkRed
+
+ // Enums from other type
+ property int e: MyQmlObject.EnumValue3
+ property int f: MyQmlObject.EnumValue4
+
+ // Enums from namespaced other type
+ property int h: Namespace.MyQmlObject.EnumValue3
+ property int i: Namespace.MyQmlObject.EnumValue4
+
+ // Count the onChanged signals to see whether
+ // they're assigned as literals or via bindings
+ property int ac: 0
+ property int bc: 0
+ property int cc: 0
+ property int dc: 0
+ property int ec: 0
+ property int fc: 0
+ property int hc: 0
+ property int ic: 0
+
+ onAChanged: ac++
+ onBChanged: bc++
+ onCChanged: cc++
+ onDChanged: dc++
+ onEChanged: ec++
+ onFChanged: fc++
+ onHChanged: hc++
+ onIChanged: ic++
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml
new file mode 100644
index 0000000000..ae43e90210
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+import com.nokia.JsModule 1.0
+import com.nokia.JsModule 1.0 as RenamedModule
+import "testJsModuleImport.js" as TestJsModuleImport
+
+QtObject {
+ id: testQtObject
+
+ property string importedScriptStringValue: ScriptAPI.greeting();
+ property string renamedScriptStringValue: RenamedModule.ScriptAPI.greeting();
+ property string reimportedScriptStringValue: TestJsModuleImport.importedValue();
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js
new file mode 100644
index 0000000000..2d21953d2c
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js
@@ -0,0 +1,5 @@
+.import com.nokia.JsModule 1.0 as JsModule
+
+function importedValue() {
+ return JsModule.ScriptAPI.greeting();
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js
new file mode 100644
index 0000000000..b90033eeb4
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js
@@ -0,0 +1,5 @@
+var major = 1
+var minor = 0
+
+function greeting() { return "Hello" }
+
diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir
new file mode 100644
index 0000000000..c33d1e7a0d
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir
@@ -0,0 +1 @@
+ScriptAPI 1.0 ScriptAPI.js
diff --git a/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml b/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml
new file mode 100644
index 0000000000..7ae099e32e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.0
+
+Item {
+ Loader {
+ source: "PropertyVarBaseItem.qml"
+ onLoaded: item.destroy()
+ }
+ Loader {
+ Component.onCompleted: setSource("PropertyVarBaseItem.qml", { random: "" })
+ onLoaded: item.destroy()
+ }
+
+ Repeater {
+ model: 1
+ Item { Component.onCompleted: destroy() }
+ }
+ Repeater {
+ model: 1
+ Item { id: me; Component.onCompleted: { setObject(me); getObject().destroy() } }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml b/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml
new file mode 100644
index 0000000000..b1b0b72a87
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+QtObject {
+ id: root
+ Component.onCompleted: { setObject(root); getObject() }
+}
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index 64e91fbc95..a79207a1c8 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -196,7 +196,7 @@ void registerTypes()
qmlRegisterModuleApi("Qt.test.qobjectApi",2,0,qobject_api); // register (qobject) module API for a uri which doesn't contain elements, major version set
qmlRegisterModuleApi("Qt.test.qobjectApiParented",1,0,qobject_api_engine_parent); // register (parented qobject) module API for a uri which doesn't contain elements
- qRegisterMetaType<MyQmlObject::MyType>("MyEnum2");
+ qRegisterMetaType<MyQmlObject::MyEnum2>("MyEnum2");
qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons");
qmlRegisterType<CircularReferenceObject>("Qt.test", 1, 0, "CircularReferenceObject");
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 861ff2e641..d932bc6d09 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -71,6 +71,8 @@ public:
private slots:
void initTestCase();
void assignBasicTypes();
+ void assignDate_data();
+ void assignDate();
void idShortcutInvalidates();
void boolPropertiesEvaluateAsBool();
void methods();
@@ -97,6 +99,8 @@ private slots:
void importScope();
void signalParameterTypes();
void objectsCompareAsEqual();
+ void componentCreation_data();
+ void componentCreation();
void dynamicCreation_data();
void dynamicCreation();
void dynamicDestruction();
@@ -129,6 +133,8 @@ private slots:
void ownership();
void cppOwnershipReturnValue();
void ownershipCustomReturnValue();
+ void ownershipRootObject();
+ void ownershipConsistency();
void qlistqobjectMethods();
void strictlyEquals();
void compiled();
@@ -255,6 +261,9 @@ void tst_qqmlecmascript::initTestCase()
{
QQmlDataTest::initTestCase();
registerTypes();
+
+ QString dataDir(dataDirectory() + QLatin1Char('/') + QLatin1String("lib"));
+ engine.addImportPath(dataDir);
}
void tst_qqmlecmascript::assignBasicTypes()
@@ -274,7 +283,7 @@ void tst_qqmlecmascript::assignBasicTypes()
QCOMPARE(object->colorProperty(), QColor("red"));
QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
- QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
+ QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC));
QCOMPARE(object->pointProperty(), QPoint(99,13));
QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
QCOMPARE(object->sizeProperty(), QSize(99, 13));
@@ -302,7 +311,7 @@ void tst_qqmlecmascript::assignBasicTypes()
QCOMPARE(object->colorProperty(), QColor("red"));
QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
- QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
+ QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC));
QCOMPARE(object->pointProperty(), QPoint(99,13));
QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
QCOMPARE(object->sizeProperty(), QSize(99, 13));
@@ -317,6 +326,28 @@ void tst_qqmlecmascript::assignBasicTypes()
}
}
+void tst_qqmlecmascript::assignDate_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::newRow("Component.onComplete JS") << testFileUrl("assignDate.qml");
+ QTest::newRow("Binding JS") << testFileUrl("assignDate.2.qml");
+ QTest::newRow("Binding UTC") << testFileUrl("assignDate.3.qml");
+ QTest::newRow("Binding JS UTC") << testFileUrl("assignDate.4.qml");
+ QTest::newRow("Binding UTC+2") << testFileUrl("assignDate.5.qml");
+ QTest::newRow("Binding JS UTC+2 ") << testFileUrl("assignDate.6.qml");
+}
+
+void tst_qqmlecmascript::assignDate()
+{
+ QFETCH(QUrl, source);
+ QQmlComponent component(&engine, source);
+ QScopedPointer<QObject> obj(component.create());
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data());
+ QVERIFY(object != 0);
+ QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
+ QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC));
+}
+
void tst_qqmlecmascript::idShortcutInvalidates()
{
{
@@ -820,6 +851,34 @@ void tst_qqmlecmascript::enums()
delete object;
}
+ // Enums as literals
+ {
+ QQmlComponent component(&engine, testFileUrl("enums.3.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ // check the values are what we expect
+ QCOMPARE(object->property("a").toInt(), 4);
+ QCOMPARE(object->property("b").toInt(), 5);
+ QCOMPARE(object->property("c").toInt(), 9);
+ QCOMPARE(object->property("d").toInt(), 13);
+ QCOMPARE(object->property("e").toInt(), 2);
+ QCOMPARE(object->property("f").toInt(), 3);
+ QCOMPARE(object->property("h").toInt(), 2);
+ QCOMPARE(object->property("i").toInt(), 3);
+
+ // count of change signals
+ QCOMPARE(object->property("ac").toInt(), 0);
+ QCOMPARE(object->property("bc").toInt(), 0);
+ QCOMPARE(object->property("cc").toInt(), 0);
+ QCOMPARE(object->property("dc").toInt(), 0);
+ QCOMPARE(object->property("ec").toInt(), 0);
+ QCOMPARE(object->property("fc").toInt(), 0);
+ QCOMPARE(object->property("hc").toInt(), 1); // namespace -> binding
+ QCOMPARE(object->property("ic").toInt(), 1); // namespace -> binding
+
+ delete object;
+ }
}
void tst_qqmlecmascript::valueTypeFunctions()
@@ -1199,6 +1258,89 @@ void tst_qqmlecmascript::aliasPropertyReset()
delete object;
}
+void tst_qqmlecmascript::componentCreation_data()
+{
+ QTest::addColumn<QString>("method");
+ QTest::addColumn<QString>("creationError");
+ QTest::addColumn<QString>("createdParent");
+
+ QTest::newRow("url")
+ << "url"
+ << ""
+ << "";
+ QTest::newRow("urlMode")
+ << "urlMode"
+ << ""
+ << "";
+ QTest::newRow("urlParent")
+ << "urlParent"
+ << ""
+ << "obj";
+ QTest::newRow("urlNullParent")
+ << "urlNullParent"
+ << ""
+ << "null";
+ QTest::newRow("urlModeParent")
+ << "urlModeParent"
+ << ""
+ << "obj";
+ QTest::newRow("urlModeNullParent")
+ << "urlModeNullParent"
+ << ""
+ << "null";
+ QTest::newRow("invalidSecondArg")
+ << "invalidSecondArg"
+ << ":40: Error: Qt.createComponent(): Invalid arguments"
+ << "";
+ QTest::newRow("invalidThirdArg")
+ << "invalidThirdArg"
+ << ":45: Error: Qt.createComponent(): Invalid parent object"
+ << "";
+ QTest::newRow("invalidMode")
+ << "invalidMode"
+ << ":50: Error: Qt.createComponent(): Invalid arguments"
+ << "";
+}
+
+/*
+Test using createComponent to dynamically generate a component.
+*/
+void tst_qqmlecmascript::componentCreation()
+{
+ QFETCH(QString, method);
+ QFETCH(QString, creationError);
+ QFETCH(QString, createdParent);
+
+ QUrl testUrl(testFileUrl("componentCreation.qml"));
+
+ if (!creationError.isEmpty()) {
+ QString warning = testUrl.toString() + creationError;
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+ }
+
+ QQmlComponent component(&engine, testUrl);
+ MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
+ QVERIFY(object != 0);
+
+ QMetaObject::invokeMethod(object, method.toUtf8());
+ QQmlComponent *created = object->componentProperty();
+
+ if (creationError.isEmpty()) {
+ QVERIFY(created);
+
+ QObject *expectedParent;
+ if (createdParent.isEmpty()) {
+ // For now, the parent should be the engine; this will change for QTBUG-24841
+ expectedParent = &engine;
+ } else if (createdParent == QLatin1String("obj")) {
+ expectedParent = object;
+ } else if (createdParent == QLatin1String("null")) {
+ expectedParent = 0;
+ }
+ QCOMPARE(created->parent(), expectedParent);
+ }
+}
+
void tst_qqmlecmascript::dynamicCreation_data()
{
QTest::addColumn<QString>("method");
@@ -2800,6 +2942,72 @@ void tst_qqmlecmascript::ownershipCustomReturnValue()
QVERIFY(source.value == 0);
}
+//the return value from getObject will be JS ownership,
+//unless strong Cpp ownership has been set
+class OwnershipChangingObject : public QObject
+{
+ Q_OBJECT
+public:
+ OwnershipChangingObject(): object(0) { }
+
+ QPointer<QObject> object;
+
+public slots:
+ QObject *getObject() { return object; }
+ void setObject(QObject *obj) { object = obj; }
+};
+
+void tst_qqmlecmascript::ownershipRootObject()
+{
+ OwnershipChangingObject own;
+ QQmlContext *context = new QQmlContext(engine.rootContext());
+ context->setContextObject(&own);
+
+ QQmlComponent component(&engine, testFileUrl("ownershipRootObject.qml"));
+ QQmlGuard<QObject> object = component.create(context);
+ QVERIFY(object);
+
+ engine.collectGarbage();
+
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ QVERIFY(own.object != 0);
+
+ delete context;
+ delete object;
+}
+
+void tst_qqmlecmascript::ownershipConsistency()
+{
+ OwnershipChangingObject own;
+ QQmlContext *context = new QQmlContext(engine.rootContext());
+ context->setContextObject(&own);
+
+ QString expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":19: Error: Invalid attempt to destroy() an indestructible object");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
+ expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":15: Error: Invalid attempt to destroy() an indestructible object");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
+ expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":6: Error: Invalid attempt to destroy() an indestructible object");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
+ expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":10: Error: Invalid attempt to destroy() an indestructible object");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
+
+ QQmlComponent component(&engine, testFileUrl("ownershipConsistency.qml"));
+ QQmlGuard<QObject> object = component.create(context);
+ QVERIFY(object);
+
+ engine.collectGarbage();
+
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ QVERIFY(own.object != 0);
+
+ delete context;
+ delete object;
+}
+
class QListQObjectMethodsObject : public QObject
{
Q_OBJECT
@@ -3299,6 +3507,17 @@ void tst_qqmlecmascript::importScripts_data()
<< QStringList()
<< (QStringList() << QLatin1String("testValue"))
<< (QVariantList() << QVariant(20));
+
+ QTest::newRow("import module which exports a script")
+ << testFileUrl("jsimport/testJsImport.qml")
+ << QString()
+ << QStringList()
+ << (QStringList() << QLatin1String("importedScriptStringValue")
+ << QLatin1String("renamedScriptStringValue")
+ << QLatin1String("reimportedScriptStringValue"))
+ << (QVariantList() << QVariant(QString("Hello"))
+ << QVariant(QString("Hello"))
+ << QVariant(QString("Hello")));
}
void tst_qqmlecmascript::importScripts()
diff --git a/tests/auto/qml/qqmlerror/.gitattributes b/tests/auto/qml/qqmlerror/.gitattributes
new file mode 100644
index 0000000000..f50af65222
--- /dev/null
+++ b/tests/auto/qml/qqmlerror/.gitattributes
@@ -0,0 +1 @@
+data/test.txt eol=lf
diff --git a/tests/auto/qml/qqmllanguage/data/globalEnums.qml b/tests/auto/qml/qqmllanguage/data/globalEnums.qml
new file mode 100644
index 0000000000..fa248d544d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/globalEnums.qml
@@ -0,0 +1,55 @@
+import QtQuick 2.0
+import Test 1.0
+
+Item {
+ MyEnum1Class {
+ id: enum1Class
+ objectName: "enum1Class"
+ }
+
+ MyEnumDerivedClass {
+ id: enumDerivedClass
+ objectName: "enumDerivedClass"
+
+ onValueAChanged: {
+ aValue = newValue;
+ }
+
+ onValueBChanged: {
+ bValue = newValue;
+ }
+
+ onValueCChanged: {
+ cValue = newValue;
+ }
+
+ onValueDChanged: {
+ dValue = newValue;
+ }
+
+ onValueEChanged: {
+ eValue = newValue;
+ }
+
+ onValueE2Changed: {
+ e2Value = newValue;
+ }
+
+ property int aValue: 0
+ property int bValue: 0
+ property int cValue: 0
+ property int dValue: 0
+ property int eValue: 0
+ property int e2Value: 0
+ }
+
+ function setEnumValues() {
+ enum1Class.setValue(MyEnum1Class.A_13);
+ enumDerivedClass.setValueA(MyEnum1Class.A_11);
+ enumDerivedClass.setValueB(MyEnum2Class.B_37);
+ enumDerivedClass.setValueC(Qt.RichText);
+ enumDerivedClass.setValueD(Qt.ElideMiddle);
+ enumDerivedClass.setValueE(MyEnum2Class.E_14);
+ enumDerivedClass.setValueE2(MyEnum2Class.E_76);
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 3c7a7c2058..5e9423761c 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -77,6 +77,10 @@ void registerTypes()
qmlRegisterType<MyVersion2Class>("Test.VersionOrder", 2,0, "MyQmlObject");
qmlRegisterType<MyQmlObject>("Test.VersionOrder", 1,0, "MyQmlObject");
+
+ qmlRegisterType<MyEnum1Class>("Test",1,0,"MyEnum1Class");
+ qmlRegisterType<MyEnum2Class>("Test",1,0,"MyEnum2Class");
+ qmlRegisterType<MyEnumDerivedClass>("Test",1,0,"MyEnumDerivedClass");
}
QVariant myCustomVariantTypeConverter(const QString &data)
@@ -85,4 +89,3 @@ QVariant myCustomVariantTypeConverter(const QString &data)
rv.a = data.toInt();
return QVariant::fromValue(rv);
}
-
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index e7294f090c..7b3265efb4 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -811,14 +811,103 @@ class MyVersion2Class : public QObject
Q_OBJECT
};
+class MyEnum1Class : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(EnumA)
+
+public:
+ MyEnum1Class() : value(A_Invalid) {}
+
+ enum EnumA
+ {
+ A_Invalid = -1,
+
+ A_11 = 11,
+ A_13 = 13
+ };
+
+ Q_INVOKABLE void setValue(EnumA v) { value = v; }
+
+ EnumA getValue() { return value; }
+
+private:
+ EnumA value;
+};
+
+class MyEnum2Class : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(EnumB)
+ Q_ENUMS(EnumE)
+
+public:
+ MyEnum2Class() : valueA(MyEnum1Class::A_Invalid), valueB(B_Invalid), valueC(Qt::PlainText),
+ valueD(Qt::ElideLeft), valueE(E_Invalid), valueE2(E_Invalid) {}
+
+ enum EnumB
+ {
+ B_Invalid = -1,
+
+ B_29 = 29,
+ B_31 = 31,
+ B_37 = 37
+ };
+
+ enum EnumE
+ {
+ E_Invalid = -1,
+
+ E_14 = 14,
+ E_76 = 76
+ };
+
+ MyEnum1Class::EnumA getValueA() { return valueA; }
+ EnumB getValueB() { return valueB; }
+ Qt::TextFormat getValueC() { return valueC; }
+ Qt::TextElideMode getValueD() { return valueD; }
+ EnumE getValueE() { return valueE; }
+ EnumE getValueE2() { return valueE2; }
+
+ Q_INVOKABLE void setValueA(MyEnum1Class::EnumA v) { valueA = v; emit valueAChanged(v); }
+ Q_INVOKABLE void setValueB(EnumB v) { valueB = v; emit valueBChanged(v); }
+ Q_INVOKABLE void setValueC(Qt::TextFormat v) { valueC = v; emit valueCChanged(v); } //registered
+ Q_INVOKABLE void setValueD(Qt::TextElideMode v) { valueD = v; emit valueDChanged(v); } //unregistered
+ Q_INVOKABLE void setValueE(EnumE v) { valueE = v; emit valueEChanged(v); }
+ Q_INVOKABLE void setValueE2(MyEnum2Class::EnumE v) { valueE2 = v; emit valueE2Changed(v); }
+
+signals:
+ void valueAChanged(MyEnum1Class::EnumA newValue);
+ void valueBChanged(MyEnum2Class::EnumB newValue);
+ void valueCChanged(Qt::TextFormat newValue);
+ void valueDChanged(Qt::TextElideMode newValue);
+ void valueEChanged(EnumE newValue);
+ void valueE2Changed(MyEnum2Class::EnumE newValue);
+
+private:
+ MyEnum1Class::EnumA valueA;
+ EnumB valueB;
+ Qt::TextFormat valueC;
+ Qt::TextElideMode valueD;
+ EnumE valueE;
+ EnumE valueE2;
+};
+
+class MyEnumDerivedClass : public MyEnum2Class
+{
+ Q_OBJECT
+};
+
+Q_DECLARE_METATYPE(MyEnum2Class::EnumB)
+Q_DECLARE_METATYPE(MyEnum1Class::EnumA)
+Q_DECLARE_METATYPE(Qt::TextFormat)
+
QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered)
QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered)
QML_DECLARE_TYPE(MyRevisionedClass)
QML_DECLARE_TYPE(MyRevisionedSubclass)
QML_DECLARE_TYPE(MySubclass)
-
-
void registerTypes();
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 266cd2a52d..837a9d2604 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -46,6 +46,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
+#include <QSignalSpy>
#include <private/qqmlproperty_p.h>
#include <private/qqmlmetatype_p.h>
@@ -176,6 +177,8 @@ private slots:
void crash1();
void crash2();
+ void globalEnums();
+
private:
QQmlEngine engine;
void testType(const QString& qml, const QString& type, const QString& error);
@@ -2285,6 +2288,64 @@ void tst_qqmllanguage::remoteLoadCrash()
delete o;
}
+// QTBUG-20639
+void tst_qqmllanguage::globalEnums()
+{
+ qRegisterMetaType<MyEnum1Class::EnumA>();
+ qRegisterMetaType<MyEnum2Class::EnumB>();
+ qRegisterMetaType<Qt::TextFormat>();
+
+ QQmlComponent component(&engine, TEST_FILE("globalEnums.qml"));
+
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ MyEnum1Class *enum1Class = o->findChild<MyEnum1Class *>(QString::fromLatin1("enum1Class"));
+ QVERIFY(enum1Class != 0);
+ QVERIFY(enum1Class->getValue() == -1);
+
+ MyEnumDerivedClass *enum2Class = o->findChild<MyEnumDerivedClass *>(QString::fromLatin1("enumDerivedClass"));
+ QVERIFY(enum2Class != 0);
+ QVERIFY(enum2Class->getValueA() == -1);
+ QVERIFY(enum2Class->getValueB() == -1);
+ QVERIFY(enum2Class->getValueC() == 0);
+ QVERIFY(enum2Class->getValueD() == 0);
+ QVERIFY(enum2Class->getValueE() == -1);
+ QVERIFY(enum2Class->getValueE2() == -1);
+
+ QVERIFY(enum2Class->property("aValue") == 0);
+ QVERIFY(enum2Class->property("bValue") == 0);
+ QVERIFY(enum2Class->property("cValue") == 0);
+ QVERIFY(enum2Class->property("dValue") == 0);
+ QVERIFY(enum2Class->property("eValue") == 0);
+ QVERIFY(enum2Class->property("e2Value") == 0);
+
+ QSignalSpy signalA(enum2Class, SIGNAL(valueAChanged(MyEnum1Class::EnumA)));
+ QSignalSpy signalB(enum2Class, SIGNAL(valueBChanged(MyEnum2Class::EnumB)));
+
+ QMetaObject::invokeMethod(o, "setEnumValues");
+
+ QVERIFY(enum1Class->getValue() == MyEnum1Class::A_13);
+ QVERIFY(enum2Class->getValueA() == MyEnum1Class::A_11);
+ QVERIFY(enum2Class->getValueB() == MyEnum2Class::B_37);
+ QVERIFY(enum2Class->getValueC() == Qt::RichText);
+ QVERIFY(enum2Class->getValueD() == Qt::ElideMiddle);
+ QVERIFY(enum2Class->getValueE() == MyEnum2Class::E_14);
+ QVERIFY(enum2Class->getValueE2() == MyEnum2Class::E_76);
+
+ QVERIFY(signalA.count() == 1);
+ QVERIFY(signalB.count() == 1);
+
+ QVERIFY(enum2Class->property("aValue") == MyEnum1Class::A_11);
+ QVERIFY(enum2Class->property("bValue") == 37);
+ QVERIFY(enum2Class->property("cValue") == 1);
+ QVERIFY(enum2Class->property("dValue") == 2);
+ QVERIFY(enum2Class->property("eValue") == 14);
+ QVERIFY(enum2Class->property("e2Value") == 76);
+
+ delete o;
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/qml/qqmlxmlhttprequest/.gitattributes b/tests/auto/qml/qqmlxmlhttprequest/.gitattributes
new file mode 100644
index 0000000000..7805eb6951
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/.gitattributes
@@ -0,0 +1,3 @@
+data/testdocument.html eol=lf
+data/redirecttarget.html eol=lf
+data/utf16.html eol=lf
diff --git a/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro b/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro
index 68c0d79f92..2726e20577 100644
--- a/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro
+++ b/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro
@@ -10,5 +10,3 @@ TESTDATA = data/*
CONFIG += parallel_test
QT += core-private gui-private qml-private testlib
-
-win32:CONFIG += insignificant_test # QTBUG-24777
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index 3761929362..804bd1a813 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -38,7 +38,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include <qtest.h>
+#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
diff --git a/tests/auto/qml/v4/data/objectToBool.qml b/tests/auto/qml/v4/data/objectToBool.qml
new file mode 100644
index 0000000000..8c8a67bee0
--- /dev/null
+++ b/tests/auto/qml/v4/data/objectToBool.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+QtObject {
+ property QtObject prop1: null
+ property QtObject prop2: QtObject {}
+
+ property bool test1: prop1 ? true : false
+ property bool test2: prop2 ? true : false
+
+ property bool test3: prop1 == false
+ property bool test4: prop1 === false
+
+ property bool test5: prop2 == false
+ property bool test6: prop2 === false
+}
+
diff --git a/tests/auto/qml/v4/tst_v4.cpp b/tests/auto/qml/v4/tst_v4.cpp
index 1c89617157..8c811f230e 100644
--- a/tests/auto/qml/v4/tst_v4.cpp
+++ b/tests/auto/qml/v4/tst_v4.cpp
@@ -133,6 +133,7 @@ void tst_v4::qtscript_data()
QTest::newRow("double bool jump") << "doubleBoolJump.qml";
QTest::newRow("unary minus") << "unaryMinus.qml";
QTest::newRow("null qobject") << "nullQObject.qml";
+ QTest::newRow("qobject -> bool") << "objectToBool.qml";
}
void tst_v4::unnecessaryReeval()
diff --git a/tests/auto/qmltest/animatedimage/stickman.gif b/tests/auto/qmltest/animatedimage/stickman.gif
new file mode 100644
index 0000000000..7c4cd18687
--- /dev/null
+++ b/tests/auto/qmltest/animatedimage/stickman.gif
Binary files differ
diff --git a/tests/auto/qmltest/animatedimage/tst_animatedimage.qml b/tests/auto/qmltest/animatedimage/tst_animatedimage.qml
new file mode 100644
index 0000000000..bc2bbea1cb
--- /dev/null
+++ b/tests/auto/qmltest/animatedimage/tst_animatedimage.qml
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+ property string srcImage: "stickman.gif"
+ property bool canconnect
+ property bool checkfinished: false
+
+ Component.onCompleted: {
+ var check = new XMLHttpRequest;
+ check.open("GET", "http://127.0.0.1:14445/stickman.gif");
+ check.onreadystatechange = function() {
+
+ console.log("Status: ", check.status)
+ console.log("Readystate", check.readyState)
+ if (check.readyState == XMLHttpRequest.DONE) {
+ if (check.status == 404) {
+ top.canconnect = false;
+ }else{
+ top.canconnect = true;
+ }
+ top.checkfinished = true;
+ }
+ }
+ check.send();
+ }
+
+ AnimatedImage {
+ id: noSource
+ source: ""
+ }
+
+ AnimatedImage {
+ id: clearSource
+ source: srcImage
+ }
+
+ AnimatedImage {
+ id: resized
+ source: srcImage
+ width: 300
+ height: 300
+ }
+
+ AnimatedImage {
+ id: smooth
+ source: srcImage
+ smooth: true
+ width: 300
+ height: 300
+ }
+
+ AnimatedImage {
+ id: tileModes1
+ source: srcImage
+ width: 100
+ height: 300
+ fillMode: AnimatedImage.Tile
+ }
+
+ AnimatedImage {
+ id: tileModes2
+ source: srcImage
+ width: 300
+ height: 150
+ fillMode: AnimatedImage.TileVertically
+ }
+ AnimatedImage {
+ id: tileModes3
+ source: srcImage
+ width: 300
+ height: 150
+ fillMode: AnimatedImage.TileHorizontally
+ }
+
+ TestCase {
+ name: "AnimatedImage"
+
+ function test_noSource() {
+ compare(noSource.source, "")
+ compare(noSource.width, 0)
+ compare(noSource.height, 0)
+ compare(noSource.fillMode, AnimatedImage.Stretch)
+ }
+
+ function test_imageSource_data() {
+ return [
+ {
+ tag: "local",
+ source: "stickman.gif",
+ remote: false,
+ error: ""
+ },
+ {
+ tag: "local not found",
+ source: "no-such-file.png",
+ remote: false,
+ error: "SUBinline:1:21: QML AnimatedImage: Error Reading Animated Image File SUBno-such-file.png"
+ },
+ {
+ tag: "remote",
+ source: "http://127.0.0.1:14445/stickman.gif",
+ remote: true,
+ error: ""
+ }
+ ]
+ }
+
+ function test_imageSource(row) {
+ var expectError = (row.error.length != 0)
+ var canconnect = false;
+
+ if (expectError) {
+ var parentUrl = Qt.resolvedUrl(".")
+ ignoreWarning(row.error.replace(/SUB/g, parentUrl))
+ }
+
+ var img = Qt.createQmlObject('import QtQuick 2.0; AnimatedImage { source: "'+row.source+'" }', top)
+
+ if (row.remote) {
+ skip("Remote solution not yet complete")
+ tryCompare(img, "status", AnimatedImage.Loading)
+ tryCompare(top, "checkfinished", true, 10000)
+ if (top.canconnect == false)
+ skip("Cannot access remote")
+ }
+
+ if (!expectError) {
+ tryCompare(img, "status", AnimatedImage.Ready, 10000)
+ compare(img.width, 160)
+ compare(img.height, 120)
+ compare(img.fillMode, AnimatedImage.Stretch)
+ } else {
+ tryCompare(img, "status", AnimatedImage.Error)
+ }
+
+ img.destroy()
+ }
+
+ function test_clearSource() {
+ compare(clearSource.source, Qt.resolvedUrl(srcImage))
+ compare(clearSource.width, 160)
+ compare(clearSource.height, 120)
+
+ srcImage = ""
+ compare(clearSource.source, "")
+ compare(clearSource.width, 0)
+ compare(clearSource.height, 0)
+ }
+
+ function test_resized() {
+ compare(resized.width, 300)
+ compare(resized.height, 300)
+ compare(resized.fillMode, AnimatedImage.Stretch)
+ }
+
+ function test_smooth() {
+ compare(smooth.smooth, true)
+ compare(smooth.width, 300)
+ compare(smooth.height, 300)
+ compare(smooth.fillMode, AnimatedImage.Stretch)
+ }
+
+ function test_tileModes() {
+ compare(tileModes1.width, 100)
+ compare(tileModes1.height, 300)
+ compare(tileModes1.fillMode, AnimatedImage.Tile)
+
+ compare(tileModes2.width, 300)
+ compare(tileModes2.height, 150)
+ compare(tileModes2.fillMode, AnimatedImage.TileVertically)
+
+ compare(tileModes3.width, 300)
+ compare(tileModes3.height, 150)
+ compare(tileModes3.fillMode, AnimatedImage.TileHorizontally)
+ }
+
+ }
+}
diff --git a/tests/auto/qmltest/borderimage/remote.sci b/tests/auto/qmltest/borderimage/remote.sci
new file mode 100644
index 0000000000..70d5213453
--- /dev/null
+++ b/tests/auto/qmltest/borderimage/remote.sci
@@ -0,0 +1,7 @@
+border.left:10
+border.top:20
+border.right:30
+border.bottom:40
+horizontalTileRule:Round
+verticalTileRule:Repeat
+source:http://127.0.0.1:14445/colors.png
diff --git a/tests/auto/qmltest/borderimage/tst_borderimage.qml b/tests/auto/qmltest/borderimage/tst_borderimage.qml
index 98a71711ed..113c0de77d 100644
--- a/tests/auto/qmltest/borderimage/tst_borderimage.qml
+++ b/tests/auto/qmltest/borderimage/tst_borderimage.qml
@@ -44,6 +44,24 @@ import QtTest 1.0
Item {
id: top
+ property bool canconnect
+ property bool checkfinished: false
+
+ Component.onCompleted: {
+ var check = new XMLHttpRequest;
+ check.open("GET", "http://127.0.0.1:14445/colors.png");
+ check.onreadystatechange = function() {
+ if (check.readyState == XMLHttpRequest.DONE) {
+ if (check.status == 404) {
+ top.canconnect = false;
+ }else{
+ top.canconnect = true;
+ }
+ top.checkfinished = true;
+ }
+ }
+ check.send();
+ }
BorderImage {
id: noSource
@@ -59,14 +77,14 @@ Item {
BorderImage {
id: resized
- source: "colors.png"
+ source: srcImage
width: 300
height: 300
}
BorderImage {
id: smooth
- source: "colors.png"
+ source: srcImage
smooth: true
width: 300
height: 300
@@ -74,7 +92,7 @@ Item {
BorderImage {
id: tileModes1
- source: "colors.png"
+ source: srcImage
width: 100
height: 300
horizontalTileMode: BorderImage.Repeat
@@ -83,7 +101,7 @@ Item {
BorderImage {
id: tileModes2
- source: "colors.png"
+ source: srcImage
width: 300
height: 150
horizontalTileMode: BorderImage.Round
@@ -114,8 +132,13 @@ Item {
source: "no-such-file.png",
remote: false,
error: "SUBinline:1:21: QML BorderImage: Cannot open: SUBno-such-file.png"
+ },
+ {
+ tag: "remote",
+ source: "http://127.0.0.1:14445/colors.png",
+ remote: true,
+ error: ""
}
- // TODO: remote tests that need to use http
]
}
@@ -130,11 +153,16 @@ Item {
('import QtQuick 2.0; BorderImage { source: "' +
row.source + '" }', top)
- if (row.remote)
+ if (row.remote) {
+ skip("Remote solution not yet complete")
tryCompare(img, "status", BorderImage.Loading)
+ tryCompare(top, "checkfinished", true, 10000)
+ if (top.canconnect == false)
+ skip("Cannot access remote")
+ }
if (!expectError) {
- tryCompare(img, "status", BorderImage.Ready)
+ tryCompare(img, "status", BorderImage.Ready, 10000)
compare(img.width, 120)
compare(img.height, 120)
compare(img.horizontalTileMode, BorderImage.Stretch)
@@ -197,25 +225,35 @@ Item {
source: "no-such-file.sci",
remote: false,
valid: false
+ },
+ {
+ tag: "remote",
+ source: "remote.sci",
+ remote: true,
+ valid: true
}
- // TODO: remote tests that need to use http
]
}
function test_sciSource(row) {
- var img = Qt.createQmlObject
- ('import QtQuick 2.0; BorderImage { source: "' +
- row.source + '"; width: 300; height: 300 }', top)
-
- if (row.remote)
- tryCompare(img, "status", BorderImage.Loading)
+ var img = Qt.createQmlObject('import QtQuick 2.0; BorderImage { height: 300; width: 300 }', top)
+
+ if (row.remote) {
+ skip("Remote solution not yet complete")
+ img.source = row.source;
+ tryCompare(top, "checkfinished", true, 10000)
+ if (top.canconnect == false)
+ skip("Cannot access remote")
+ }else{
+ img.source = row.source;
+ }
compare(img.source, Qt.resolvedUrl(row.source))
compare(img.width, 300)
compare(img.height, 300)
if (row.valid) {
- tryCompare(img, "status", BorderImage.Ready)
+ tryCompare(img, "status", BorderImage.Ready, 10000)
compare(img.border.left, 10)
compare(img.border.top, 20)
compare(img.border.right, 30)
diff --git a/tests/auto/qmltest/fontloader/dummy.ttf b/tests/auto/qmltest/fontloader/dummy.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qmltest/fontloader/dummy.ttf
diff --git a/tests/auto/qmltest/fontloader/tarzeau_ocr_a.ttf b/tests/auto/qmltest/fontloader/tarzeau_ocr_a.ttf
new file mode 100644
index 0000000000..cf93f9651f
--- /dev/null
+++ b/tests/auto/qmltest/fontloader/tarzeau_ocr_a.ttf
Binary files differ
diff --git a/tests/auto/qmltest/fontloader/tst_fontloader.qml b/tests/auto/qmltest/fontloader/tst_fontloader.qml
new file mode 100644
index 0000000000..d389283e49
--- /dev/null
+++ b/tests/auto/qmltest/fontloader/tst_fontloader.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ FontLoader {
+ id: fontloader
+ }
+
+ FontLoader {
+ id: fontswitch
+ }
+
+ TextInput {
+ id: testinput
+ font.family: fontloader.name
+ }
+
+
+
+ TestCase {
+ name: "FontLoader"
+
+ function test_fontloading() {
+ compare(fontloader.status, FontLoader.Null)
+ compare(testinput.font.family, "")
+ fontloader.source = "tarzeau_ocr_a.ttf";
+ tryCompare(fontloader.status, FontLoader.Loading)
+ tryCompare(fontloader.status, FontLoader.Ready)
+ compare(testinput.font.family, "OCRA")
+ fontloader.source = "dummy.ttf";
+ tryCompare(fontloader.status, FontLoader.Error)
+ compare(testinput.font.family, "")
+ fontloader.source = "";
+ fontloader.name = "Courier";
+ tryCompare(fontloader.status, FontLoader.Ready)
+ compare(testinput.font.family, "Courier")
+ }
+
+ function test_fontswitching() {
+ compare(fontswitch.status, FontLoader.Null)
+ fontswitch.source = "tarzeau_ocr_a.ttf";
+ tryCompare(fontswitch.status, FontLoader.Loading)
+ tryCompare(fontswitch.status, FontLoader.Ready)
+ tryCompare(fontswitch.name, "OCRA")
+ fontswitch.source = "";
+ fontswitch.name = "Courier";
+ tryCompare(fontswitch.status, FontLoader.Ready)
+ tryCompare(fontswitch.name, "Courier")
+ fontswitch.source = "tarzeau_ocr_a.ttf";
+ tryCompare(fontswitch.status, FontLoader.Loading)
+ tryCompare(fontswitch.status, FontLoader.Ready)
+ compare(fontswitch.name, "OCRA")
+ }
+ }
+}
diff --git a/tests/auto/qmltest/gradient/tst_gradient.qml b/tests/auto/qmltest/gradient/tst_gradient.qml
new file mode 100644
index 0000000000..ed587502b6
--- /dev/null
+++ b/tests/auto/qmltest/gradient/tst_gradient.qml
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ Gradient {
+ id: emptygradient
+ }
+
+ Gradient {
+ id: twogradients
+ GradientStop { position: 0.0; color: "red" }
+ GradientStop { position: 1.0; color: "green" }
+ }
+
+ Gradient {
+ id: elevengradients
+ GradientStop { position: 0.0; color: "red" }
+ GradientStop { position: 0.1; color: "orange" }
+ GradientStop { position: 0.2; color: "yellow" }
+ GradientStop { position: 0.3; color: "green" }
+ GradientStop { position: 0.4; color: "blue" }
+ GradientStop { position: 0.5; color: "violet" }
+ GradientStop { position: 0.6; color: "indigo" }
+ GradientStop { position: 0.7; color: "brown" }
+ GradientStop { position: 0.8; color: "lightgray" }
+ GradientStop { position: 0.9; color: "gray" }
+ GradientStop { position: 1.0; color: "black" }
+ }
+
+ Gradient {
+ id: movedgradients
+ property real stopposition: 0.5
+ GradientStop { position: 0.0; color: "red" }
+ GradientStop { position: movedgradients.stopposition; color: "blue" }
+ GradientStop { position: 1.0; color: "green" }
+ }
+
+ Gradient {
+ id: defaultgradient
+ GradientStop { }
+ GradientStop { position: 1.0; color: "red" }
+ }
+
+ TestCase {
+ name: "Gradient"
+
+ function test_empty() {
+ compare(emptygradient.stops.length, 0)
+ }
+
+ function test_lengthtwo() {
+ compare(twogradients.stops.length, 2)
+ compare(twogradients.stops[0].color.toString(), "#ff0000")
+ compare(twogradients.stops[1].color.toString(), "#008000")
+ }
+
+ function test_multiplestops() {
+ compare(elevengradients.stops.length, 11)
+ compare(elevengradients.stops[0].color.toString(), "#ff0000")
+ compare(elevengradients.stops[4].color.toString(), "#0000ff")
+ compare(elevengradients.stops[4].position, 0.4)
+ compare(elevengradients.stops[9].position, 0.9)
+ }
+
+ function test_moved() {
+ compare(movedgradients.stops.length, 3)
+ compare(movedgradients.stops[1].position, 0.5)
+ movedgradients.stopposition = 0.3;
+ compare(movedgradients.stops[1].position, 0.3)
+ }
+
+ function test_default() {
+ compare(defaultgradient.stops.length, 2)
+ compare(defaultgradient.stops[0].color.toString(), "#000000")
+ }
+ }
+}
diff --git a/tests/auto/qmltest/image/logo.png b/tests/auto/qmltest/image/logo.png
new file mode 100644
index 0000000000..d75936b007
--- /dev/null
+++ b/tests/auto/qmltest/image/logo.png
Binary files differ
diff --git a/tests/auto/qmltest/image/tst_image.qml b/tests/auto/qmltest/image/tst_image.qml
new file mode 100644
index 0000000000..f6ad01014a
--- /dev/null
+++ b/tests/auto/qmltest/image/tst_image.qml
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ property string srcImage: "logo.png"
+ property bool canconnect
+ property bool checkfinished: false
+
+ Component.onCompleted: {
+ var check = new XMLHttpRequest;
+ check.open("GET", "http://127.0.0.1:14445/logo.png");
+ check.onreadystatechange = function() {
+ if (check.readyState == XMLHttpRequest.DONE) {
+ if (check.status == 404) {
+ top.canconnect = false;
+ } else {
+ top.canconnect = true;
+ }
+ top.checkfinished = true;
+ }
+ }
+ check.send();
+ }
+
+ Image {
+ id: noSource
+ source: ""
+ }
+
+ Image {
+ id: clearSource
+ source: srcImage
+ }
+
+ Image {
+ id: resized
+ source: srcImage
+ width: 300
+ height: 300
+ }
+
+ Image {
+ id: smooth
+ source: srcImage
+ smooth: true
+ width: 300
+ height: 300
+ }
+
+ Image {
+ id: tileModes1
+ source: srcImage
+ width: 100
+ height: 300
+ fillMode: Image.Tile
+ }
+
+ Image {
+ id: tileModes2
+ source: srcImage
+ width: 300
+ height: 150
+ fillMode: Image.TileVertically
+ }
+ Image {
+ id: tileModes3
+ source: srcImage
+ width: 300
+ height: 150
+ fillMode: Image.TileHorizontally
+ }
+
+ TestCase {
+ name: "Image"
+
+ function test_noSource() {
+ compare(noSource.source, "")
+ compare(noSource.width, 0)
+ compare(noSource.height, 0)
+ compare(noSource.fillMode, Image.Stretch)
+ }
+
+ function test_imageSource_data() {
+ return [
+ {
+ tag: "local",
+ source: "logo.png",
+ remote: false,
+ error: ""
+ },
+ {
+ tag: "local not found",
+ source: "no-such-file.png",
+ remote: false,
+ error: "SUBinline:1:21: QML Image: Cannot open: SUBno-such-file.png"
+ },
+ {
+ tag: "remote",
+ source: "http://127.0.0.1:14445/logo.png",
+ remote: true,
+ error: ""
+ }
+ ]
+ }
+
+ function test_imageSource(row) {
+ var expectError = (row.error.length != 0)
+ if (expectError) {
+ var parentUrl = Qt.resolvedUrl(".")
+ ignoreWarning(row.error.replace(/SUB/g, parentUrl))
+ }
+
+ var img = Qt.createQmlObject('import QtQuick 2.0; Image { source: "'+row.source+'" }', top)
+
+ if (row.remote) {
+ skip("Remote solution not yet complete")
+ tryCompare(img, "status", Image.Loading)
+ tryCompare(top, "checkfinished", true, 10000)
+ if (top.canconnect == false)
+ skip("Cannot access remote")
+ }
+
+ if (!expectError) {
+ tryCompare(img, "status", Image.Ready, 10000)
+ compare(img.width, 59)
+ compare(img.height, 71)
+ compare(img.fillMode, Image.Stretch)
+ } else {
+ tryCompare(img, "status", Image.Error)
+ }
+
+ img.destroy()
+ }
+
+ function test_clearSource() {
+ compare(clearSource.source, Qt.resolvedUrl(srcImage))
+ compare(clearSource.width, 59)
+ compare(clearSource.height, 71)
+
+ srcImage = ""
+ compare(clearSource.source, "")
+ compare(clearSource.width, 0)
+ compare(clearSource.height, 0)
+ }
+
+ function test_resized() {
+ compare(resized.width, 300)
+ compare(resized.height, 300)
+ compare(resized.fillMode, Image.Stretch)
+ }
+
+ function test_smooth() {
+ compare(smooth.smooth, true)
+ compare(smooth.width, 300)
+ compare(smooth.height, 300)
+ compare(smooth.fillMode, Image.Stretch)
+ }
+
+ function test_tileModes() {
+ compare(tileModes1.width, 100)
+ compare(tileModes1.height, 300)
+ compare(tileModes1.fillMode, Image.Tile)
+
+ compare(tileModes2.width, 300)
+ compare(tileModes2.height, 150)
+ compare(tileModes2.fillMode, Image.TileVertically)
+
+ compare(tileModes3.width, 300)
+ compare(tileModes3.height, 150)
+ compare(tileModes3.fillMode, Image.TileHorizontally)
+ }
+
+ }
+}
diff --git a/tests/auto/qmltest/listmodel/tst_listmodel.qml b/tests/auto/qmltest/listmodel/tst_listmodel.qml
new file mode 100644
index 0000000000..7c393a1899
--- /dev/null
+++ b/tests/auto/qmltest/listmodel/tst_listmodel.qml
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+ ListModel { id: emptymodel }
+ ListModel { id: manyitems }
+ ListModel { id: insertmodel }
+ ListModel { id: move; ListElement { name: "Element0" } ListElement { name: "Element1" } }
+ ListModel { id: firstmodel; ListElement { name: "FirstModelElement0" } }
+ ListModel { id: secondmodel; ListElement { name: "SecondModelElement0" } ListElement { name: "SecondModelElement1" } }
+ ListModel { id: altermodel; ListElement { name: "AlterModelElement0" } ListElement { name: "AlterModelElement1" } }
+
+ TestCase {
+ name: "ListModel"
+
+ function test_empty() {
+ compare(emptymodel.count, 0)
+ emptymodel.clear();
+ compare(emptymodel.count, 0)
+ }
+
+ function test_multipleitems_data() {
+ return [
+ {
+ tag: "10items",
+ numitems: 10
+ },
+ {
+ tag: "100items",
+ numitems: 100
+ },
+ {
+ tag: "10000items",
+ numitems: 10000
+ }
+ ]
+ }
+
+ function test_multipleitems(row) {
+ var i;
+ manyitems.clear();
+ compare(manyitems.count, 0)
+ for (i = 0; i < row.numitems; ++i) {
+ manyitems.append({"name":"Item"+i})
+ }
+ compare(manyitems.count, row.numitems)
+ }
+
+ function test_insert() {
+ insertmodel.insert(0, {"name": "Element0"})
+ compare(insertmodel.get(0).name, "Element0")
+ insertmodel.insert(1, {"name": "Element1"})
+ compare(insertmodel.get(1).name, "Element1")
+ }
+
+ function test_altermodeled() {
+ tryCompare(altermodel.count, 2)
+ compare(altermodel.get(0).name, "AlterModelElement0")
+ compare(altermodel.get(1).name, "AlterModelElement1")
+ altermodel.append({"name":"AlterModelElement2"})
+ tryCompare(altermodel.count, 3)
+ compare(altermodel.get(0).name, "AlterModelElement0")
+ compare(altermodel.get(1).name, "AlterModelElement1")
+ compare(altermodel.get(2).name, "AlterModelElement2")
+ altermodel.insert(2,{"name":"AlterModelElement1.5"})
+ tryCompare(altermodel.count, 4)
+ compare(altermodel.get(0).name, "AlterModelElement0")
+ compare(altermodel.get(1).name, "AlterModelElement1")
+ compare(altermodel.get(2).name, "AlterModelElement1.5")
+ compare(altermodel.get(3).name, "AlterModelElement2")
+ tryCompare(altermodel.count, 4)
+ altermodel.move(2,1,1);
+ compare(altermodel.get(0).name, "AlterModelElement0")
+ compare(altermodel.get(1).name, "AlterModelElement1.5")
+ compare(altermodel.get(2).name, "AlterModelElement1")
+ compare(altermodel.get(3).name, "AlterModelElement2")
+ altermodel.remove(1,2)
+ tryCompare(altermodel.count, 2)
+ compare(altermodel.get(0).name, "AlterModelElement0")
+ compare(altermodel.get(1).name, "AlterModelElement2")
+ altermodel.set(1,{"name":"AlterModelElement1"})
+ compare(altermodel.get(0).name, "AlterModelElement0")
+ compare(altermodel.get(1).name, "AlterModelElement1")
+ altermodel.setProperty(0, "name", "AlteredProperty")
+ compare(altermodel.get(0).name, "AlteredProperty")
+ altermodel.clear()
+ tryCompare(altermodel.count, 0)
+ compare(altermodel.get(0), undefined)
+ }
+ }
+}
diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml
new file mode 100644
index 0000000000..535c551ede
--- /dev/null
+++ b/tests/auto/qmltest/listview/tst_listview.qml
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ ListView {
+ id: emptylist
+ height: 20
+ width: 50
+ }
+
+ ListView {
+ id: viewmanyitems
+ model: manyitems
+ }
+
+ ListView {
+ id: modelchange
+ model: firstmodel
+ delegate: Text { text: model.name }
+ }
+
+ ListView {
+ id: modelalter
+ model: altermodel
+ delegate: Text { text: model.name }
+ }
+
+ ListModel { id: emptymodel }
+ ListModel { id: manyitems }
+ ListModel { id: firstmodel; ListElement { name: "FirstModelElement0" } }
+ ListModel { id: secondmodel; ListElement { name: "SecondModelElement0" } ListElement { name: "SecondModelElement1" } }
+ ListModel { id: altermodel; ListElement { name: "AlterModelElement0" } ListElement { name: "AlterModelElement1" } }
+
+ TestCase {
+ name: "ListView"
+
+ function test_empty() {
+ compare(emptylist.count, 0)
+ emptylist.model = emptymodel;
+ compare(emptylist.count, 0)
+ }
+
+ function test_multipleitems_data() {
+ return [
+ {
+ tag: "10items",
+ numitems: 10
+ },
+ {
+ tag: "100items",
+ numitems: 100
+ },
+ {
+ tag: "10000items",
+ numitems: 10000
+ }
+ ]
+ }
+
+ function test_multipleitems(row) {
+ var i;
+ manyitems.clear();
+ compare(manyitems.count, 0)
+ for (i = 0; i < row.numitems; ++i) {
+ manyitems.append({"name":"Item"+i})
+ }
+ compare(manyitems.count, row.numitems)
+ tryCompare(viewmanyitems.count, row.numitems)
+ }
+
+ function test_modelchange() {
+ tryCompare(modelchange.count, 1)
+ modelchange.currentIndex = 0;
+ compare(modelchange.currentItem.text, "FirstModelElement0")
+ modelchange.model = secondmodel;
+ tryCompare(modelchange.count, 2)
+ modelchange.currentIndex = 0;
+ compare(modelchange.currentItem.text, "SecondModelElement0")
+ modelchange.currentIndex = 1;
+ compare(modelchange.currentItem.text, "SecondModelElement1")
+ }
+
+ function test_modelaltered() {
+ tryCompare(modelalter.count, 2)
+ modelalter.currentIndex = 0;
+ compare(modelalter.currentItem.text, "AlterModelElement0")
+ modelalter.currentIndex = 1;
+ compare(modelalter.currentItem.text, "AlterModelElement1")
+ altermodel.append({"name":"AlterModelElement2"})
+ tryCompare(modelalter.count, 3)
+ modelalter.currentIndex = 0;
+ compare(modelalter.currentItem.text, "AlterModelElement0")
+ modelalter.currentIndex = 1;
+ compare(modelalter.currentItem.text, "AlterModelElement1")
+ modelalter.currentIndex = 2;
+ compare(modelalter.currentItem.text, "AlterModelElement2")
+ altermodel.insert(2,{"name":"AlterModelElement1.5"})
+ tryCompare(modelalter.count, 4)
+ modelalter.currentIndex = 0;
+ compare(modelalter.currentItem.text, "AlterModelElement0")
+ modelalter.currentIndex = 1;
+ compare(modelalter.currentItem.text, "AlterModelElement1")
+ modelalter.currentIndex = 2;
+ compare(modelalter.currentItem.text, "AlterModelElement1.5")
+ modelalter.currentIndex = 3;
+ compare(modelalter.currentItem.text, "AlterModelElement2")
+ altermodel.move(2,1,1);
+ tryCompare(modelalter.count, 4)
+ modelalter.currentIndex = 0;
+ compare(modelalter.currentItem.text, "AlterModelElement0")
+ modelalter.currentIndex = 1;
+ compare(modelalter.currentItem.text, "AlterModelElement1.5")
+ modelalter.currentIndex = 2;
+ compare(modelalter.currentItem.text, "AlterModelElement1")
+ modelalter.currentIndex = 3;
+ compare(modelalter.currentItem.text, "AlterModelElement2")
+ altermodel.remove(1,2)
+ tryCompare(modelalter.count, 2)
+ modelalter.currentIndex = 0;
+ compare(modelalter.currentItem.text, "AlterModelElement0")
+ modelalter.currentIndex = 1;
+ compare(modelalter.currentItem.text, "AlterModelElement2")
+ altermodel.set(1,{"name":"AlterModelElement1"})
+ modelalter.currentIndex = 0;
+ compare(modelalter.currentItem.text, "AlterModelElement0")
+ modelalter.currentIndex = 1;
+ compare(modelalter.currentItem.text, "AlterModelElement1")
+ altermodel.clear()
+ tryCompare(modelalter.count, 0)
+ compare(modelalter.currentItem, null)
+ }
+ }
+}
diff --git a/tests/auto/qmltest/rectangle/tst_rectangle.qml b/tests/auto/qmltest/rectangle/tst_rectangle.qml
new file mode 100644
index 0000000000..038bb96c0f
--- /dev/null
+++ b/tests/auto/qmltest/rectangle/tst_rectangle.qml
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ Rectangle { id: empty }
+
+ Rectangle { id: radius }
+
+ Rectangle {
+ id: resized
+ width: 300
+ height: 300
+ }
+
+ Rectangle {
+ id: smooth
+ smooth: true
+ width: 300
+ height: 300
+ }
+
+ Rectangle {
+ id: gradient
+ width: 100
+ height: 300
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "red" }
+ GradientStop { position: 0.5; color: "yellow" }
+ GradientStop { position: 1.0; color: "green" }
+ }
+ }
+
+ Rectangle {
+ id: rectangleborder
+ width: 300
+ height: 150
+ border.width: 1
+ border.color: "gray"
+ }
+
+ TestCase {
+ name: "Rectangle"
+
+ function test_empty() {
+ compare(empty.width, 0)
+ compare(empty.height, 0)
+ }
+
+ function test_radius() {
+ compare(radius.width, 0)
+ compare(radius.height, 0)
+ compare(radius.radius, 0)
+ radius.height = 100;
+ radius.width = 100;
+ radius.radius = 10;
+ compare(radius.width, 100)
+ compare(radius.height, 100)
+ compare(radius.radius, 10)
+ }
+
+ function test_resized() {
+ compare(resized.width, 300)
+ compare(resized.height, 300)
+ resized.height = 500;
+ resized.width = 500;
+ compare(resized.width, 500)
+ compare(resized.height, 500)
+ }
+
+ function test_smooth() {
+ compare(smooth.smooth, true)
+ compare(smooth.width, 300)
+ compare(smooth.height, 300)
+
+ }
+
+ function test_gradient() {
+ var grad = gradient.gradient;
+ var gstops = grad.stops;
+ compare(gstops[0].color.toString(), "#ff0000")
+ compare(gstops[1].color.toString(), "#ffff00")
+ compare(gstops[2].color.toString(), "#008000")
+ }
+
+ function test_borders() {
+ compare(rectangleborder.border.width, 1)
+ compare(rectangleborder.border.color.toString(), "#808080")
+ rectangleborder.border.width = 10;
+ rectangleborder.border.color = "brown";
+ compare(rectangleborder.border.width, 10)
+ compare(rectangleborder.border.color.toString(), "#a52a2a")
+ }
+
+ }
+}
diff --git a/tests/auto/qmltest/text/tst_text.qml b/tests/auto/qmltest/text/tst_text.qml
new file mode 100644
index 0000000000..599fabcc8b
--- /dev/null
+++ b/tests/auto/qmltest/text/tst_text.qml
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ Text {
+ id: emptyText
+ }
+
+ Text {
+ id: txtfamily
+ text: "Hello world!"
+ font.family: "Courier"
+ }
+
+ Text {
+ id: txtcolor
+ text: "Hello world!"
+ color: "red"
+ }
+
+ Text {
+ id: txtelide
+ text: "Hello world!"
+ elide: Text.ElideRight
+ }
+
+ Text {
+ property string first: "Hello world!"
+ property string second: "Hello\nworld!"
+ property string third: "Hello\nworld\n!"
+
+ id: txtlinecount
+ text: first
+ width: 100
+ wrapMode: Text.WrapAnywhere
+ }
+
+ TestCase {
+ name: "Text"
+
+ function test_empty() {
+ compare(emptyText.text, "")
+ }
+
+ function test_family() {
+ compare(txtfamily.font.family, "Courier")
+ txtfamily.font.family = "Helvetica";
+ compare(txtfamily.font.family, "Helvetica")
+ }
+
+ function test_color() {
+ compare(txtcolor.color, "#ff0000")
+ txtcolor.color = "blue";
+ compare(txtcolor.color, "#0000ff")
+ }
+
+ function test_elide() {
+ compare(txtelide.elide, Text.ElideRight)
+ txtelide.elide = Text.ElideLeft;
+ compare(txtelide.elide, Text.ElideLeft)
+ txtelide.elide = Text.ElideMiddle;
+ compare(txtelide.elide, Text.ElideMiddle)
+ }
+
+ function test_linecount() {
+ compare(txtlinecount.lineCount, 1)
+ txtlinecount.text = txtlinecount.second;
+ compare(txtlinecount.lineCount, 2)
+ txtlinecount.text = txtlinecount.third;
+ compare(txtlinecount.lineCount, 3)
+ txtlinecount.text = txtlinecount.first;
+ compare(txtlinecount.lineCount, 1)
+ txtlinecount.width = 50;
+ compare(txtlinecount.lineCount, 3)
+ }
+
+ }
+}
diff --git a/tests/auto/qmltest/textedit/tst_textedit.qml b/tests/auto/qmltest/textedit/tst_textedit.qml
new file mode 100644
index 0000000000..a0f0a8c8d7
--- /dev/null
+++ b/tests/auto/qmltest/textedit/tst_textedit.qml
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ TextEdit {
+ id: emptyText
+ height: 20
+ width: 50
+ }
+
+ TextEdit {
+ id: txtfamily
+ text: "Hello world!"
+ font.family: "Courier"
+ height: 20
+ width: 50
+ }
+
+ TextEdit {
+ id: txtcolor
+ text: "Hello world!"
+ color: "red"
+ height: 20
+ width: 50
+ }
+
+ TextEdit {
+ id: txtentry
+ text: ""
+ height: 20
+ width: 50
+ }
+
+ TextEdit {
+ id: txtfunctions
+ text: "The quick brown fox jumped over the lazy dog"
+ height: 20
+ width: 50
+ }
+
+ TextEdit {
+ id: txtlines
+ property string styledtextvalue: "Line 1<br>Line 2<br>Line 3"
+ text: "Line 1\nLine 2\nLine 3"
+ textFormat: Text.PlainText
+ }
+
+ TestCase {
+ name: "TextEdit"
+ when: windowShown
+
+ function test_empty() {
+ compare(emptyText.text, "")
+ }
+
+ function test_family() {
+ compare(txtfamily.font.family, "Courier")
+ txtfamily.font.family = "Helvetica";
+ compare(txtfamily.font.family, "Helvetica")
+ }
+
+ function test_color() {
+ compare(txtcolor.color, "#ff0000")
+ txtcolor.color = "blue";
+ compare(txtcolor.color, "#0000ff")
+ }
+
+ function test_textentry() {
+ txtentry.focus = true;
+ compare(txtentry.text, "")
+ keyClick(Qt.Key_H)
+ keyClick(Qt.Key_E)
+ keyClick(Qt.Key_L)
+ keyClick(Qt.Key_L)
+ keyClick(Qt.Key_O)
+ keyClick(Qt.Key_Space)
+ keyClick(Qt.Key_W)
+ keyClick(Qt.Key_O)
+ keyClick(Qt.Key_R)
+ keyClick(Qt.Key_L)
+ keyClick(Qt.Key_D)
+ compare(txtentry.text, "hello world")
+ }
+
+ function test_functions() {
+ compare(txtfunctions.getText(4,9), "quick")
+ txtfunctions.select(4,9);
+ compare(txtfunctions.selectedText, "quick")
+ txtfunctions.deselect();
+ compare(txtfunctions.selectedText, "")
+ txtfunctions.select(4,9);
+ txtfunctions.cut();
+ compare(txtfunctions.text, "The brown fox jumped over the lazy dog")
+ txtfunctions.text = "Qt";
+ txtfunctions.insert(txtfunctions.text.length, " ")
+ compare(txtfunctions.text, "Qt ");
+ txtfunctions.cursorPosition = txtfunctions.text.length;
+ txtfunctions.paste();
+ compare(txtfunctions.text, "Qt quick");
+ txtfunctions.cursorPosition = txtfunctions.text.length;
+ txtfunctions.selectWord();
+ compare(txtfunctions.selectedText, "quick")
+ txtfunctions.copy();
+ txtfunctions.selectAll();
+ compare(txtfunctions.selectedText, "Qt quick")
+ txtfunctions.deselect();
+ compare(txtfunctions.selectedText, "")
+ txtfunctions.paste();
+ compare(txtfunctions.text, "Qt quickquick");
+ }
+
+ function test_linecounts() {
+ compare(txtlines.lineCount, 3)
+ txtlines.text = txtlines.styledtextvalue;
+ compare(txtlines.text, "Line 1<br>Line 2<br>Line 3")
+ tryCompare(txtlines.lineCount, 1)
+ txtlines.textFormat = Text.StyledText;
+ tryCompare(txtlines.lineCount, 3)
+ txtlines.textFormat = Text.RichText;
+ tryCompare(txtlines.lineCount, 3)
+ }
+ }
+}
diff --git a/tests/auto/qmltest/textinput/tst_textinput.qml b/tests/auto/qmltest/textinput/tst_textinput.qml
new file mode 100644
index 0000000000..2399456730
--- /dev/null
+++ b/tests/auto/qmltest/textinput/tst_textinput.qml
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QtTest 1.0
+
+Item {
+ id: top
+
+ TextInput {
+ id: emptyText
+ height: 20
+ width: 50
+ }
+
+ TextInput {
+ id: txtfamily
+ text: "Hello world!"
+ font.family: "Courier"
+ height: 20
+ width: 50
+ }
+
+ TextInput {
+ id: txtcolor
+ text: "Hello world!"
+ color: "red"
+ height: 20
+ width: 50
+ }
+
+ TextInput {
+ id: txtentry
+ text: ""
+ height: 20
+ width: 50
+ }
+
+ TextInput {
+ id: txtfunctions
+ text: "The quick brown fox jumped over the lazy dog"
+ height: 20
+ width: 50
+ }
+
+ TextInput {
+ id: txtintvalidator
+ text: ""
+ height: 20
+ width: 50
+ validator: IntValidator { id: iv; top: 20; bottom: 10; }
+ }
+
+ TextInput {
+ id: txtdoublevalidator
+ text: ""
+ height: 20
+ width: 50
+ validator: DoubleValidator { id: dv; top: 2.0; bottom: 1.0; }
+ }
+
+ TextInput {
+ id: txtregexpvalidator
+ text: ""
+ height: 20
+ width: 50
+ validator: RegExpValidator { id: rv; regExp: /[a-z]{3}/ }
+ }
+
+
+
+ TestCase {
+ name: "TextInput"
+ when: windowShown
+
+ function test_empty() {
+ compare(emptyText.text, "")
+ }
+
+ function test_family() {
+ compare(txtfamily.font.family, "Courier")
+ txtfamily.font.family = "Helvetica";
+ compare(txtfamily.font.family, "Helvetica")
+ }
+
+ function test_color() {
+ compare(txtcolor.color, "#ff0000")
+ txtcolor.color = "blue";
+ compare(txtcolor.color, "#0000ff")
+ }
+
+ function test_textentry() {
+ txtentry.focus = true;
+ compare(txtentry.text, "")
+ keyClick(Qt.Key_H)
+ keyClick(Qt.Key_E)
+ keyClick(Qt.Key_L)
+ keyClick(Qt.Key_L)
+ keyClick(Qt.Key_O)
+ keyClick(Qt.Key_Space)
+ keyClick(Qt.Key_W)
+ keyClick(Qt.Key_O)
+ keyClick(Qt.Key_R)
+ keyClick(Qt.Key_L)
+ keyClick(Qt.Key_D)
+ compare(txtentry.text, "hello world")
+ }
+
+ function test_functions() {
+ compare(txtfunctions.getText(4,9), "quick")
+ txtfunctions.select(4,9);
+ compare(txtfunctions.selectedText, "quick")
+ txtfunctions.deselect();
+ compare(txtfunctions.selectedText, "")
+ txtfunctions.select(4,9);
+ txtfunctions.cut();
+ compare(txtfunctions.text, "The brown fox jumped over the lazy dog")
+ txtfunctions.text = "Qt";
+ txtfunctions.insert(txtfunctions.text.length, " ")
+ compare(txtfunctions.text, "Qt ");
+ txtfunctions.cursorPosition = txtfunctions.text.length;
+ txtfunctions.paste();
+ compare(txtfunctions.text, "Qt quick");
+ txtfunctions.cursorPosition = txtfunctions.text.length;
+ txtfunctions.selectWord();
+ compare(txtfunctions.selectedText, "quick")
+ txtfunctions.copy();
+ txtfunctions.selectAll();
+ compare(txtfunctions.selectedText, "Qt quick")
+ txtfunctions.deselect();
+ compare(txtfunctions.selectedText, "")
+ txtfunctions.paste();
+ compare(txtfunctions.text, "Qt quickquick");
+ }
+
+ function test_intvalidators_data() {
+ return [
+ {
+ tag: "toolow",
+ testnumber: "5",
+ acceptable: false
+ },
+ {
+ tag: "toohigh",
+ testnumber: "50",
+ acceptable: false
+ },
+ {
+ tag: "onlowerbounds",
+ testnumber: "10",
+ acceptable: true
+ },
+ {
+ tag: "onupperbounds",
+ testnumber: "20",
+ acceptable: true
+ },
+ {
+ tag: "middle",
+ testnumber: "15",
+ acceptable: true
+ },
+ {
+ tag: "negativemiddle",
+ testnumber: "-15",
+ acceptable: false
+ }
+ ]
+
+ }
+
+ function test_intvalidators(row) {
+ compare(txtintvalidator.validator.top, 20)
+ compare(txtintvalidator.validator.bottom, 10)
+ txtintvalidator.text = row.testnumber;
+ compare(txtintvalidator.acceptableInput, row.acceptable)
+ }
+
+ function test_doublevalidators_data() {
+ return [
+ {
+ tag: "toolow",
+ testnumber: "0.5",
+ acceptable: false
+ },
+ {
+ tag: "toohigh",
+ testnumber: "2.5",
+ acceptable: false
+ },
+ {
+ tag: "onlowerbounds",
+ testnumber: "1.0",
+ acceptable: true
+ },
+ {
+ tag: "onupperbounds",
+ testnumber: "2.0",
+ acceptable: true
+ },
+ {
+ tag: "middle",
+ testnumber: "1.5",
+ acceptable: true
+ },
+ {
+ tag: "negativemiddle",
+ testnumber: "-1.5",
+ acceptable: false
+ }
+ ]
+
+ }
+
+ function test_doublevalidators(row) {
+ compare(txtdoublevalidator.validator.top, 2.0)
+ compare(txtdoublevalidator.validator.bottom, 1.0)
+ txtdoublevalidator.text = row.testnumber;
+ compare(txtdoublevalidator.acceptableInput, row.acceptable)
+ }
+
+ function test_regexpvalidators_data() {
+ return [
+ {
+ tag: "toolow",
+ testtext: "ab",
+ acceptable: false
+ },
+ {
+ tag: "toohigh",
+ testtext: "abcd",
+ acceptable: false
+ },
+ {
+ tag: "acceptable",
+ testtext: "abc",
+ acceptable: true
+ }
+ ]
+
+ }
+
+ function test_regexpvalidators(row) {
+ compare(txtregexpvalidator.validator.regExp, /[a-z]{3}/)
+ txtregexpvalidator.text = row.testtext;
+ compare(txtregexpvalidator.acceptableInput, row.acceptable)
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml
new file mode 100644
index 0000000000..1ee76f6906
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+Item {
+ id: root
+ width: 450; height: 600
+
+ Rectangle {
+ objectName:"rect"
+ id: rect
+ x:200
+ y:500
+ width: 225; height: 40
+ color: "lightsteelblue"
+ }
+ PathAnimation {
+ id:anim
+ running:true
+ duration: 200
+
+ easing.type: Easing.InOutBack
+
+ target:rect
+ path: Path {
+ PathLine { x: 0; y: 0 }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index d71100d120..166f4b8276 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -107,6 +107,7 @@ private slots:
void pauseBug();
void loopingBug();
void anchorBug();
+ void pathAnimationInOutBackBug();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -455,6 +456,13 @@ void tst_qquickanimations::pathInterpolator()
QCOMPARE(interpolator->x(), qreal(300));
QCOMPARE(interpolator->y(), qreal(300));
QCOMPARE(interpolator->angle(), qreal(0));
+
+ //for path interpulator the progress value must be [0,1] range.
+ interpolator->setProgress(1.1);
+ QCOMPARE(interpolator->progress(), qreal(1));
+
+ interpolator->setProgress(-0.000123);
+ QCOMPARE(interpolator->progress(), qreal(0));
}
void tst_qquickanimations::pathInterpolatorBackwardJump()
@@ -1171,6 +1179,22 @@ void tst_qquickanimations::runningTrueBug()
QVERIFY(cloud->x() > qreal(0));
}
+//QTBUG-24308
+void tst_qquickanimations::pathAnimationInOutBackBug()
+{
+ //ensure we don't pass bad progress value (out of [0,1]) to QQuickPath::backwardsPointAt()
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("pathAnimationInOutBackCrash.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+
+ QQuickRectangle *rect = item->findChild<QQuickRectangle *>("rect");
+ QVERIFY(rect);
+ QTest::qWait(1000);
+ QCOMPARE(rect->x(), qreal(0));
+ QCOMPARE(rect->y(), qreal(0));
+}
+
//QTBUG-12805
void tst_qquickanimations::nonTransitionBug()
{
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
index ffe6583d2e..c33901d294 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
@@ -4,6 +4,7 @@ import "testhelper.js" as Helper
Canvas {
id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded
+ smooth: false
TestCase {
name: "arc"; when: windowShown
function test_angle_1() {
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
index 8609ad0332..84bfc1a8db 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
@@ -4,6 +4,7 @@ import "testhelper.js" as Helper
Canvas {
id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded
+ smooth: false
TestCase {
name: "arcTo"; when: windowShown
function test_coincide() {
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
index 6aaecbdfa5..f72e5b9eaa 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
@@ -4,6 +4,7 @@ import "testhelper.js" as Helper
Canvas {
id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded
+ smooth: false
TestCase {
name: "path"; when: windowShown
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
index 2521643837..c81ef73b90 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
@@ -4,6 +4,7 @@ import "testhelper.js" as Helper
Canvas {
id:canvas; width:100;height:50; renderTarget:Canvas.Image; renderStrategy:Canvas.Threaded
+ smooth: false
TestCase {
name: "strokeStyle"; when: windowShown
function test_default() {
diff --git a/tests/auto/quick/qquickflickable/data/cancel.qml b/tests/auto/quick/qquickflickable/data/cancel.qml
new file mode 100644
index 0000000000..d1c3fddbf2
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/cancel.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+
+Flickable {
+ width: 200; height: 200
+ contentWidth: row.width; contentHeight: row.height
+
+ Row {
+ id: row
+ objectName: "row"
+ Repeater {
+ model: 4
+ Rectangle { width: 400; height: 600; color: "yellow"; border.width: 1 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 4b157a434b..2ed42e7f0f 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -77,6 +77,7 @@ private slots:
void disabled();
void flickVelocity();
void margins();
+ void cancel();
private:
QQmlEngine engine;
@@ -440,6 +441,19 @@ void tst_qquickflickable::movingAndDragging()
// wait for any motion to end
QTRY_VERIFY(flickable->isMoving() == false);
+ // Vertical with a quick press-move-release: should cause a flick in release.
+ QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged()));
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
+ QTest::qWait(10);
+ QTest::mouseMove(canvas, QPoint(50, 40));
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 40));
+
+ QCOMPARE(vFlickSpy.count(), 1);
+
+ // wait for any motion to end
+ QTRY_VERIFY(flickable->isMoving() == false);
+
//Horizontal
vDragSpy.clear();
hDragSpy.clear();
@@ -492,7 +506,7 @@ void tst_qquickflickable::movingAndDragging()
vMoveSpy.clear();
hMoveSpy.clear();
moveSpy.clear();
- QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged()));
+ vFlickSpy.clear();
QSignalSpy hFlickSpy(flickable, SIGNAL(flickingHorizontallyChanged()));
QSignalSpy flickSpy(flickable, SIGNAL(flickingChanged()));
@@ -657,6 +671,41 @@ void tst_qquickflickable::margins()
delete root;
}
+void tst_qquickflickable::cancel()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(testFileUrl("cancel.qml"));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
+ QVERIFY(flickable != 0);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10, 10));
+ // drag out of bounds
+ QTest::mouseMove(canvas, QPoint(50, 50));
+ QTest::mouseMove(canvas, QPoint(100, 100));
+ QTest::mouseMove(canvas, QPoint(150, 150));
+
+ QVERIFY(flickable->contentX() != 0);
+ QVERIFY(flickable->contentY() != 0);
+ QVERIFY(flickable->isMoving());
+ QVERIFY(flickable->isDragging());
+
+ // grabbing mouse will cancel flickable interaction.
+ QQuickItem *item = canvas->rootObject()->findChild<QQuickItem*>("row");
+ item->grabMouse();
+
+ QTRY_COMPARE(flickable->contentX(), 0.);
+ QTRY_COMPARE(flickable->contentY(), 0.);
+ QTRY_VERIFY(!flickable->isMoving());
+ QTRY_VERIFY(!flickable->isDragging());
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 10));
+}
+
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"
diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
index f99c26803d..10f81accbf 100644
--- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
+++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
@@ -116,6 +116,9 @@ void tst_qquickfontloader::namedFont()
void tst_qquickfontloader::localFont()
{
+#if defined(Q_OS_WIN)
+ QSKIP("Windows doesn't support font loading.");
+#endif
QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("tarzeau_ocr_a.ttf").toString() + "\" }";
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
@@ -129,6 +132,9 @@ void tst_qquickfontloader::localFont()
void tst_qquickfontloader::failLocalFont()
{
+#if defined(Q_OS_WIN)
+ QSKIP("Windows doesn't support font loading.");
+#endif
QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("dummy.ttf").toString() + "\" }";
QTest::ignoreMessage(QtWarningMsg, QString("file::2:1: QML FontLoader: Cannot load font: \"" + testFileUrl("dummy.ttf").toString() + "\"").toUtf8().constData());
QQmlComponent component(&engine);
@@ -143,6 +149,9 @@ void tst_qquickfontloader::failLocalFont()
void tst_qquickfontloader::webFont()
{
+#if defined(Q_OS_WIN)
+ QSKIP("Windows doesn't support font loading.");
+#endif
QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/tarzeau_ocr_a.ttf\" }";
QQmlComponent component(&engine);
@@ -157,6 +166,9 @@ void tst_qquickfontloader::webFont()
void tst_qquickfontloader::redirWebFont()
{
+#if defined(Q_OS_WIN)
+ QSKIP("Windows doesn't support font loading.");
+#endif
server.addRedirect("olddir/oldname.ttf","../tarzeau_ocr_a.ttf");
QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/olddir/oldname.ttf\" }";
@@ -173,6 +185,9 @@ void tst_qquickfontloader::redirWebFont()
void tst_qquickfontloader::failWebFont()
{
+#if defined(Q_OS_WIN)
+ QSKIP("Windows doesn't support font loading.");
+#endif
QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/nonexist.ttf\" }";
QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML FontLoader: Cannot load font: \"http://localhost:14448/nonexist.ttf\"");
QQmlComponent component(&engine);
@@ -187,6 +202,9 @@ void tst_qquickfontloader::failWebFont()
void tst_qquickfontloader::changeFont()
{
+#if defined(Q_OS_WIN)
+ QSKIP("Windows doesn't support font loading.");
+#endif
QString componentStr = "import QtQuick 2.0\nFontLoader { source: font }";
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("font", testFileUrl("tarzeau_ocr_a.ttf"));
@@ -226,6 +244,9 @@ void tst_qquickfontloader::changeFont()
void tst_qquickfontloader::changeFontSourceViaState()
{
+#if defined(Q_OS_WIN)
+ QSKIP("Windows doesn't support font loading.");
+#endif
QQuickView canvas(testFileUrl("qtbug-20268.qml"));
canvas.show();
canvas.requestActivateWindow();
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 88ed94d8bc..c7b5ca6b40 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -3691,31 +3691,32 @@ void tst_QQuickGridView::margins()
QQuickItem *contentItem = gridview->contentItem();
QTRY_VERIFY(contentItem != 0);
- QCOMPARE(gridview->contentX(), -240+30.);
- QCOMPARE(gridview->xOrigin(), 0.);
+ QTRY_COMPARE(gridview->contentX(), -240+50.);
+ QTRY_COMPARE(gridview->xOrigin(), 0.);
// check end bound
gridview->positionViewAtEnd();
qreal pos = gridview->contentX();
gridview->setContentX(pos - 80);
gridview->returnToBounds();
- QTRY_COMPARE(gridview->contentX(), pos - 50);
+ QTRY_COMPARE(gridview->contentX(), pos - 30);
// remove item before visible and check that left margin is maintained
// and xOrigin is updated
gridview->setContentX(-400);
+ QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
model.removeItems(0, 4);
- QTest::qWait(100);
+ QTRY_COMPARE(model.count(), gridview->count());
gridview->setContentX(-240+50);
gridview->returnToBounds();
QCOMPARE(gridview->xOrigin(), -100.);
- QTRY_COMPARE(gridview->contentX(), -240-70.);
+ QTRY_COMPARE(gridview->contentX(), -240-50.);
- // reduce left margin (i.e. right side due to RTL)
+ // reduce right margin
pos = gridview->contentX();
- gridview->setLeftMargin(20);
+ gridview->setRightMargin(40);
QCOMPARE(gridview->xOrigin(), -100.);
- QTRY_COMPARE(gridview->contentX(), -240-80.);
+ QTRY_COMPARE(gridview->contentX(), -240-100 + 40.);
// check end bound
gridview->positionViewAtEnd();
@@ -3723,11 +3724,11 @@ void tst_QQuickGridView::margins()
pos = gridview->contentX();
gridview->setContentX(pos - 80);
gridview->returnToBounds();
- QTRY_COMPARE(gridview->contentX(), pos - 50);
+ QTRY_COMPARE(gridview->contentX(), pos - 30);
- // reduce right margin (i.e. left side due to RTL)
+ // reduce left margin
pos = gridview->contentX();
- gridview->setRightMargin(40);
+ gridview->setLeftMargin(20);
QCOMPARE(gridview->xOrigin(), 0.);
QTRY_COMPARE(gridview->contentX(), pos+10);
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 9fdfa78559..abd0da8ac1 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -181,7 +181,7 @@ void tst_qquickitem::initTestCase()
qmlRegisterType<TestPolishItem>("Qt.test", 1, 0, "TestPolishItem");
}
-// Focus has no effect when outside a canvas
+// Focus still updates when outside a canvas
void tst_qquickitem::noCanvas()
{
QQuickItem *root = new TestItem;
@@ -201,7 +201,7 @@ void tst_qquickitem::noCanvas()
scopedChild2->setFocus(true);
QCOMPARE(root->hasFocus(), true);
QCOMPARE(child->hasFocus(), false);
- QCOMPARE(scope->hasFocus(), true);
+ QCOMPARE(scope->hasFocus(), false);
QCOMPARE(scopedChild->hasFocus(), false);
QCOMPARE(scopedChild2->hasFocus(), true);
@@ -210,10 +210,10 @@ void tst_qquickitem::noCanvas()
scopedChild->setFocus(true);
scope->setFocus(false);
QCOMPARE(root->hasFocus(), false);
- QCOMPARE(child->hasFocus(), true);
+ QCOMPARE(child->hasFocus(), false);
QCOMPARE(scope->hasFocus(), false);
QCOMPARE(scopedChild->hasFocus(), true);
- QCOMPARE(scopedChild2->hasFocus(), true);
+ QCOMPARE(scopedChild2->hasFocus(), false);
delete root;
}
@@ -434,7 +434,7 @@ void tst_qquickitem::addedToCanvas()
c1->setFocus(true);
c2->setFocus(true);
focusState[item].set(true, true);
- focusState[c1].set(true, false);
+ focusState[c1].set(false, false);
focusState[c2].set(true, false);
focusState.active(item);
FVERIFY();
@@ -458,14 +458,14 @@ void tst_qquickitem::addedToCanvas()
focusState << tree << c1 << c2;
c1->setFocus(true);
c2->setFocus(true);
- focusState[c1].set(true, false);
+ focusState[c1].set(false, false);
focusState[c2].set(true, false);
FVERIFY();
tree->setParentItem(canvas.rootItem());
- focusState[c1].set(true, true);
- focusState[c2].set(false, false);
- focusState.active(c1);
+ focusState[c1].set(false, false);
+ focusState[c2].set(true, true);
+ focusState.active(c2);
FVERIFY();
}
@@ -481,19 +481,19 @@ void tst_qquickitem::addedToCanvas()
focusState << tree << c1 << c2;
c1->setFocus(true);
c2->setFocus(true);
- focusState[c1].set(true, false);
+ focusState[c1].set(false, false);
focusState[c2].set(true, false);
FVERIFY();
tree->setParentItem(canvas.rootItem());
- focusState[c1].set(true, false);
- focusState[c2].set(false, false);
+ focusState[c1].set(false, false);
+ focusState[c2].set(true, false);
FVERIFY();
tree->setFocus(true);
focusState[tree].set(true, true);
- focusState[c1].set(true, true);
- focusState.active(c1);
+ focusState[c2].set(true, true);
+ focusState.active(c2);
FVERIFY();
}
@@ -511,15 +511,15 @@ void tst_qquickitem::addedToCanvas()
c1->setFocus(true);
c2->setFocus(true);
focusState[tree].set(true, false);
- focusState[c1].set(true, false);
+ focusState[c1].set(false, false);
focusState[c2].set(true, false);
FVERIFY();
tree->setParentItem(canvas.rootItem());
focusState[tree].set(true, true);
- focusState[c1].set(true, true);
- focusState[c2].set(false, false);
- focusState.active(c1);
+ focusState[c1].set(false, false);
+ focusState[c2].set(true, true);
+ focusState.active(c2);
FVERIFY();
}
@@ -540,22 +540,22 @@ void tst_qquickitem::addedToCanvas()
c2->setFocus(true);
focusState[child].set(true, true);
focusState[tree].set(true, false);
- focusState[c1].set(true, false);
+ focusState[c1].set(false, false);
focusState[c2].set(true, false);
focusState.active(child);
FVERIFY();
tree->setParentItem(canvas.rootItem());
focusState[tree].set(false, false);
- focusState[c1].set(true, false);
- focusState[c2].set(false, false);
+ focusState[c1].set(false, false);
+ focusState[c2].set(true, false);
FVERIFY();
tree->setFocus(true);
focusState[child].set(false, false);
focusState[tree].set(true, true);
- focusState[c1].set(true, true);
- focusState.active(c1);
+ focusState[c2].set(true, true);
+ focusState.active(c2);
FVERIFY();
}
}
@@ -674,6 +674,40 @@ void tst_qquickitem::changeParent()
FVERIFY();
}
+ // child has active focus, then its fs parent changes parent to 0, then
+ // child is deleted, then its parent changes again to a valid parent
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *item = new TestFocusScope(canvas.rootItem());
+ QQuickItem *child = new TestItem(item);
+ QQuickItem *child2 = new TestItem;
+
+ FocusState focusState;
+ focusState << item << child;
+ FVERIFY();
+
+ item->setFocus(true);
+ child->setFocus(true);
+ focusState[child].set(true, true);
+ focusState[item].set(true, true);
+ focusState.active(child);
+ FVERIFY();
+
+ item->setParentItem(0);
+ focusState[child].set(true, false);
+ focusState[item].set(true, false);
+ focusState.active(0);
+ FVERIFY();
+
+ focusState.remove(child);
+ delete child;
+ item->setParentItem(canvas.rootItem());
+ focusState[item].set(true, true);
+ focusState.active(item);
+ FVERIFY();
+ }
}
void tst_qquickitem::multipleFocusClears()
diff --git a/tests/auto/quick/qquickitemlayer/data/Effect.qml b/tests/auto/quick/qquickitemlayer/data/Effect.qml
index 630c8f90ed..678f86538d 100644
--- a/tests/auto/quick/qquickitemlayer/data/Effect.qml
+++ b/tests/auto/quick/qquickitemlayer/data/Effect.qml
@@ -2,19 +2,19 @@ import QtQuick 2.0
Item
{
- width: 100
+ width: 200
height: 100
Rectangle {
id: box
- width: 100
+ width: 200
height: 100
color: "#0000ff"
Rectangle {
- x: 50
- width: 50
+ x: 100
+ width: 100
height: 100
color: "#00ff00"
}
diff --git a/tests/auto/quick/qquickitemlayer/data/SourceRect.qml b/tests/auto/quick/qquickitemlayer/data/SourceRect.qml
index 7cc7e8b21e..a161760028 100644
--- a/tests/auto/quick/qquickitemlayer/data/SourceRect.qml
+++ b/tests/auto/quick/qquickitemlayer/data/SourceRect.qml
@@ -2,12 +2,12 @@ import QtQuick 2.0
Item
{
- width: 100
+ width: 200
height: 100
Rectangle {
id: box
- width: 100
+ width: 200
height: 100
color: "#ff0000"
diff --git a/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml b/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml
index ccd515652a..427bd41310 100644
--- a/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml
+++ b/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml
@@ -2,19 +2,19 @@ import QtQuick 2.0
Item
{
- width: 100
+ width: 200
height: 100
Rectangle {
id: box
- width: 100
+ width: 200
height: 100
color: "#0000ff"
Rectangle {
- x: 50
- width: 50
+ x: 100
+ width: 100
height: 100
color: "#00ff00"
}
diff --git a/tests/auto/quick/qquicklistview/data/margins2.qml b/tests/auto/quick/qquicklistview/data/margins2.qml
index e11c803c4b..4b1f2546bf 100644
--- a/tests/auto/quick/qquicklistview/data/margins2.qml
+++ b/tests/auto/quick/qquicklistview/data/margins2.qml
@@ -9,9 +9,9 @@ Item {
}
ListView {
objectName: "listview"
- topMargin: 20
+ topMargin: 40
bottomMargin: 20
- leftMargin: 20
+ leftMargin: 40
rightMargin: 20
anchors.fill: parent
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 202f5164af..461a6b6750 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -4290,6 +4290,13 @@ void tst_QQuickListView::marginsResize()
QFETCH(qreal, start);
QFETCH(qreal, end);
+ QPoint flickStart(20, 20);
+ QPoint flickEnd(20, 20);
+ if (orientation == QQuickListView::Vertical)
+ flickStart.ry() += 180;
+ else
+ flickStart.rx() += (layoutDirection == Qt::LeftToRight) ? 180 : -180;
+
QQuickView *canvas = getView();
canvas->setSource(testFileUrl("margins2.qml"));
@@ -4316,6 +4323,14 @@ void tst_QQuickListView::marginsResize()
else
QTRY_COMPARE(listview->contentX(), end);
+ // flick past the end and check content pos still settles on correct extents
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(listview->isMoving() == false);
+ if (orientation == QQuickListView::Vertical)
+ QTRY_COMPARE(listview->contentY(), end);
+ else
+ QTRY_COMPARE(listview->contentX(), end);
+
// back to top - top margin should be visible.
listview->setCurrentIndex(0);
if (orientation == QQuickListView::Vertical)
@@ -4323,6 +4338,14 @@ void tst_QQuickListView::marginsResize()
else
QTRY_COMPARE(listview->contentX(), start);
+ // flick past the beginning and check content pos still settles on correct extents
+ flick(canvas, flickEnd, flickStart, 180);
+ QTRY_VERIFY(listview->isMoving() == false);
+ if (orientation == QQuickListView::Vertical)
+ QTRY_COMPARE(listview->contentY(), start);
+ else
+ QTRY_COMPARE(listview->contentX(), start);
+
releaseView(canvas);
}
@@ -4333,9 +4356,11 @@ void tst_QQuickListView::marginsResize_data()
QTest::addColumn<qreal>("start");
QTest::addColumn<qreal>("end");
- QTest::newRow("vertical") << QQuickListView::Vertical << Qt::LeftToRight << -20.0 << 1020.0;
- QTest::newRow("horizontal") << QQuickListView::Horizontal << Qt::LeftToRight << -20.0 << 1020.0;
- QTest::newRow("horizontal, rtl") << QQuickListView::Horizontal << Qt::RightToLeft << -180.0 << -1220.0;
+ // in Right to Left mode, leftMargin still means leftMargin - it doesn't reverse to mean rightMargin
+
+ QTest::newRow("vertical") << QQuickListView::Vertical << Qt::LeftToRight << -40.0 << 1020.0;
+ QTest::newRow("horizontal") << QQuickListView::Horizontal << Qt::LeftToRight << -40.0 << 1020.0;
+ QTest::newRow("horizontal, rtl") << QQuickListView::Horizontal << Qt::RightToLeft << -180.0 << -1240.0;
}
void tst_QQuickListView::snapToItem_data()
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index bdf47fa9e9..01781f7b54 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -929,7 +929,7 @@ void tst_QQuickLoader::asynchronous_clear()
QVERIFY(!loader->item());
QCOMPARE(loader->status(), QQuickLoader::Loading);
- QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
+ QTRY_COMPARE(engine.incubationController()->incubatingObjectCount(), 1);
// clear before component created
root->setProperty("comp", "");
@@ -942,7 +942,7 @@ void tst_QQuickLoader::asynchronous_clear()
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
// check loading component
- root->setProperty("comp", "Rect120x60.qml");
+ root->setProperty("comp", "BigComponent.qml");
QMetaObject::invokeMethod(root, "loadComponent");
QVERIFY(!loader->item());
@@ -953,6 +953,8 @@ void tst_QQuickLoader::asynchronous_clear()
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->status(), QQuickLoader::Ready);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+
+ delete root;
}
void tst_QQuickLoader::simultaneousSyncAsync()
diff --git a/tests/auto/quick/qquickpathview/data/dragpath.qml b/tests/auto/quick/qquickpathview/data/dragpath.qml
index f9c6615b04..6ba778bb80 100644
--- a/tests/auto/quick/qquickpathview/data/dragpath.qml
+++ b/tests/auto/quick/qquickpathview/data/dragpath.qml
@@ -14,6 +14,7 @@ PathView {
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
Text {
+ objectName: "text"
text: "current index: " + parent.currentIndex
}
}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 8866cafd80..613156b2f5 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -123,6 +123,7 @@ private slots:
void creationContext();
void currentOffsetOnInsertion();
void asynchronous();
+ void cancelDrag();
};
class TestObject : public QObject
@@ -1453,6 +1454,41 @@ void tst_QQuickPathView::missingPercent()
delete obj;
}
+void tst_QQuickPathView::cancelDrag()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(testFileUrl("dragpath.qml"));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_COMPARE(canvas, qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
+ QVERIFY(pathview != 0);
+
+ // drag between snap points
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10,100));
+ QTest::qWait(100);
+ QTest::mouseMove(canvas, QPoint(30, 100));
+ QTest::mouseMove(canvas, QPoint(85, 100));
+
+ QTRY_VERIFY(pathview->offset() != qFloor(pathview->offset()));
+ QTRY_VERIFY(pathview->isMoving());
+
+ // steal mouse grab - cancels PathView dragging
+ QQuickItem *item = canvas->rootObject()->findChild<QQuickItem*>("text");
+ item->grabMouse();
+
+ // returns to a snap point.
+ QTRY_VERIFY(pathview->offset() == qFloor(pathview->offset()));
+ QTRY_VERIFY(!pathview->isMoving());
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(40,100));
+
+ delete canvas;
+}
+
+
QTEST_MAIN(tst_QQuickPathView)
#include "tst_qquickpathview.moc"
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 77f0ec190d..affb355837 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -107,6 +107,8 @@ private slots:
void implicitSize_data();
void implicitSize();
void contentSize();
+ void implicitSizeBinding_data();
+ void implicitSizeBinding();
void lineLaidOut();
@@ -1069,11 +1071,11 @@ void tst_qquicktext::smooth()
for (int i = 0; i < standard.size(); i++)
{
{
- QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + standard.at(i) + "\" }";
+ QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), true);
+ QCOMPARE(textObject->smooth(), false);
delete textObject;
}
@@ -1082,7 +1084,7 @@ void tst_qquicktext::smooth()
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), false);
+ QCOMPARE(textObject->smooth(), true);
delete textObject;
}
@@ -1090,11 +1092,11 @@ void tst_qquicktext::smooth()
for (int i = 0; i < richText.size(); i++)
{
{
- QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }";
+ QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), true);
+ QCOMPARE(textObject->smooth(), false);
delete textObject;
}
@@ -1103,7 +1105,7 @@ void tst_qquicktext::smooth()
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), false);
+ QCOMPARE(textObject->smooth(), true);
delete textObject;
}
@@ -1548,29 +1550,36 @@ void tst_qquicktext::implicitSize_data()
QTest::addColumn<QString>("width");
QTest::addColumn<QString>("wrap");
QTest::addColumn<QString>("elide");
- QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone";
- QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone";
- QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone";
- QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight";
- QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight";
- QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone";
- QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone";
- QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone";
- QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone";
- QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight";
- QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight";
- QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone";
+ QTest::addColumn<QString>("format");
+ QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText";
+ QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText";
+ QTest::newRow("styledtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText";
+ QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText";
+ QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText";
+ QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText";
+ QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText";
+ QTest::newRow("styledtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText";
+ QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText";
+ QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText";
+ QTest::newRow("styledtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText";
+ QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText";
+ QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText";
+ QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText";
+ QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText";
+ QTest::newRow("styledtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText";
}
void tst_qquicktext::implicitSize()
{
QFETCH(QString, text);
QFETCH(QString, width);
+ QFETCH(QString, format);
QFETCH(QString, wrap);
QFETCH(QString, elide);
QString componentStr = "import QtQuick 2.0\nText { "
"text: \"" + text + "\"; "
"width: " + width + "; "
+ "textFormat: " + format + "; "
"wrapMode: " + wrap + "; "
"elide: " + elide + "; "
"maximumLineCount: 1 }";
@@ -1631,6 +1640,35 @@ void tst_qquicktext::contentSize()
QCOMPARE(spy.count(), ++spyCount);
}
+void tst_qquicktext::implicitSizeBinding_data()
+{
+ implicitSize_data();
+}
+
+void tst_qquicktext::implicitSizeBinding()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, wrap);
+ QFETCH(QString, format);
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }";
+
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
+
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetWidth();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetHeight();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+}
+
void tst_qquicktext::lineLaidOut()
{
QQuickView *canvas = createView(testFile("lineLayout.qml"));
diff --git a/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml b/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml
index 7c7cb0b6fc..b7a15962f4 100644
--- a/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml
+++ b/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml
@@ -2,6 +2,6 @@ import QtQuick 2.0
TextEdit {
focus: true
- text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ text: "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"
selectByMouse: true
}
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index a90b23dfd7..83e7e78866 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -69,6 +69,7 @@
Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode)
+Q_DECLARE_METATYPE(Qt::Key)
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
@@ -151,6 +152,8 @@ private slots:
void implicitSize_data();
void implicitSize();
void contentSize();
+ void implicitSizeBinding_data();
+ void implicitSizeBinding();
void preeditCursorRectangle();
void inputMethodComposing();
@@ -185,7 +188,7 @@ private:
void simulateKeys(QWindow *window, const QList<Key> &keys);
void simulateKeys(QWindow *window, const QKeySequence &sequence);
- void simulateKey(QQuickView *, int key, Qt::KeyboardModifiers modifiers = 0);
+ void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = 0);
QStringList standard;
QStringList richText;
@@ -1012,23 +1015,88 @@ void tst_qquicktextedit::persistentSelection()
void tst_qquicktextedit::focusOnPress()
{
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }";
- QQmlComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->focusOnPress(), true);
- }
+ QString componentStr =
+ "import QtQuick 2.0\n"
+ "TextEdit {\n"
+ "property bool selectOnFocus: false\n"
+ "width: 100; height: 50\n"
+ "activeFocusOnPress: true\n"
+ "text: \"Hello World\"\n"
+ "onFocusChanged: { if (focus && selectOnFocus) selectAll() }"
+ " }";
+ QQmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->focusOnPress(), true);
+ QCOMPARE(textEditObject->hasFocus(), false);
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }";
- QQmlComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->focusOnPress(), false);
- }
+ QSignalSpy focusSpy(textEditObject, SIGNAL(focusChanged(bool)));
+ QSignalSpy activeFocusSpy(textEditObject, SIGNAL(focusChanged(bool)));
+ QSignalSpy activeFocusOnPressSpy(textEditObject, SIGNAL(activeFocusOnPressChanged(bool)));
+
+ textEditObject->setFocusOnPress(true);
+ QCOMPARE(textEditObject->focusOnPress(), true);
+ QCOMPARE(activeFocusOnPressSpy.count(), 0);
+
+ QQuickCanvas canvas;
+ canvas.resize(100, 50);
+ textEditObject->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ QCOMPARE(textEditObject->hasFocus(), false);
+ QCOMPARE(textEditObject->hasActiveFocus(), false);
+
+ QPoint centerPoint(canvas.width()/2, canvas.height()/2);
+ Qt::KeyboardModifiers noModifiers = 0;
+ QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(textEditObject->hasFocus(), true);
+ QCOMPARE(textEditObject->hasActiveFocus(), true);
+ QCOMPARE(focusSpy.count(), 1);
+ QCOMPARE(activeFocusSpy.count(), 1);
+ QCOMPARE(textEditObject->selectedText(), QString());
+ QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+
+ textEditObject->setFocusOnPress(false);
+ QCOMPARE(textEditObject->focusOnPress(), false);
+ QCOMPARE(activeFocusOnPressSpy.count(), 1);
+
+ textEditObject->setFocus(false);
+ QCOMPARE(textEditObject->hasFocus(), false);
+ QCOMPARE(textEditObject->hasActiveFocus(), false);
+ QCOMPARE(focusSpy.count(), 2);
+ QCOMPARE(activeFocusSpy.count(), 2);
+
+ // Wait for double click timeout to expire before clicking again.
+ QTest::qWait(400);
+ QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(textEditObject->hasFocus(), false);
+ QCOMPARE(textEditObject->hasActiveFocus(), false);
+ QCOMPARE(focusSpy.count(), 2);
+ QCOMPARE(activeFocusSpy.count(), 2);
+ QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+
+ textEditObject->setFocusOnPress(true);
+ QCOMPARE(textEditObject->focusOnPress(), true);
+ QCOMPARE(activeFocusOnPressSpy.count(), 2);
+
+ // Test a selection made in the on(Active)FocusChanged handler isn't overwritten.
+ textEditObject->setProperty("selectOnFocus", true);
+
+ QTest::qWait(400);
+ QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(textEditObject->hasFocus(), true);
+ QCOMPARE(textEditObject->hasActiveFocus(), true);
+ QCOMPARE(focusSpy.count(), 3);
+ QCOMPARE(activeFocusSpy.count(), 3);
+ QCOMPARE(textEditObject->selectedText(), textEditObject->text());
+ QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
}
void tst_qquicktextedit::selection()
@@ -1562,21 +1630,41 @@ void tst_qquicktextedit::mouseSelection_data()
QTest::addColumn<int>("from");
QTest::addColumn<int>("to");
QTest::addColumn<QString>("selectedText");
+ QTest::addColumn<bool>("focus");
+ QTest::addColumn<bool>("focusOnPress");
+ QTest::addColumn<bool>("doubleClick");
// import installed
- QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678";
- QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString();
- QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString();
- QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString();
- QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789";
- QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << false;
+ QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << false;
+ QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << false;
+ QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << false;
+ QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << false;
+
+ QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << false;
+ QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << false;
+
+ QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << false;
+ QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << false;
+
+ QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+ QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+ QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+ QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+ QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+ QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+ QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+ QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
+
+ QTest::newRow("off double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << true;
+ QTest::newRow("off double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("off double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("off double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("off double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("off double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("off double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("off double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("off double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
}
void tst_qquicktextedit::mouseSelection()
@@ -1585,6 +1673,9 @@ void tst_qquicktextedit::mouseSelection()
QFETCH(int, from);
QFETCH(int, to);
QFETCH(QString, selectedText);
+ QFETCH(bool, focus);
+ QFETCH(bool, focusOnPress);
+ QFETCH(bool, doubleClick);
QQuickView canvas(QUrl::fromLocalFile(qmlfile));
@@ -1597,9 +1688,14 @@ void tst_qquicktextedit::mouseSelection()
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
QVERIFY(textEditObject != 0);
+ textEditObject->setFocus(focus);
+ textEditObject->setFocusOnPress(focusOnPress);
+
// press-and-drag-and-release from x1 to x2
QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
+ if (doubleClick)
+ QTest::mouseClick(&canvas, Qt::LeftButton, 0, p1);
QTest::mousePress(&canvas, Qt::LeftButton, 0, p1);
QTest::mouseMove(&canvas, p2);
QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2);
@@ -1608,7 +1704,10 @@ void tst_qquicktextedit::mouseSelection()
// Clicking and shift to clicking between the same points should select the same text.
textEditObject->setCursorPosition(0);
- QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1);
+ if (doubleClick)
+ QTest::mouseDClick(&canvas, Qt::LeftButton, 0, p1);
+ else
+ QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1);
QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2);
QTest::qWait(50);
QTRY_COMPARE(textEditObject->selectedText(), selectedText);
@@ -2155,7 +2254,7 @@ void tst_qquicktextedit::readOnly()
QCOMPARE(edit->cursorPosition(), edit->text().length());
}
-void tst_qquicktextedit::simulateKey(QQuickView *view, int key, Qt::KeyboardModifiers modifiers)
+void tst_qquicktextedit::simulateKey(QWindow *view, int key, Qt::KeyboardModifiers modifiers)
{
QKeyEvent press(QKeyEvent::KeyPress, key, modifiers);
QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers);
@@ -2415,17 +2514,19 @@ void tst_qquicktextedit::implicitSize_data()
{
QTest::addColumn<QString>("text");
QTest::addColumn<QString>("wrap");
- QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap";
- QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap";
- QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap";
- QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap";
+ QTest::addColumn<QString>("format");
+ QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap" << "TextEdit.PlainText";
+ QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap" << "TextEdit.RichText";
+ QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap" << "TextEdit.PlainText";
+ QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap" << "TextEdit.RichText";
}
void tst_qquicktextedit::implicitSize()
{
QFETCH(QString, text);
QFETCH(QString, wrap);
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
+ QFETCH(QString, format);
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + "; textFormat: " + format + " }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
@@ -2466,6 +2567,34 @@ void tst_qquicktextedit::contentSize()
QCOMPARE(spy.count(), 3);
}
+void tst_qquicktextedit::implicitSizeBinding_data()
+{
+ implicitSize_data();
+}
+
+void tst_qquicktextedit::implicitSizeBinding()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, wrap);
+ QFETCH(QString, format);
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit *>(object.data());
+
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetWidth();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetHeight();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+}
+
void tst_qquicktextedit::preeditCursorRectangle()
{
QString preeditText = "super";
@@ -3255,63 +3384,118 @@ void tst_qquicktextedit::keySequence_data()
QTest::addColumn<int>("cursorPosition");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QString>("selectedText");
+ QTest::addColumn<Qt::Key>("layoutDirection");
// standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog"
QTest::newRow("select all")
<< standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0
- << 44 << standard.at(0) << standard.at(0);
+ << 44 << standard.at(0) << standard.at(0)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select start of line")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfLine) << 5 << 5
+ << 0 << standard.at(0) << standard.at(0).mid(0, 5)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select start of block")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfBlock) << 5 << 5
+ << 0 << standard.at(0) << standard.at(0).mid(0, 5)
+ << Qt::Key_Direction_L;
QTest::newRow("select end of line")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
- << 44 << standard.at(0) << standard.at(0).mid(5);
+ << 44 << standard.at(0) << standard.at(0).mid(5)
+ << Qt::Key_Direction_L;
QTest::newRow("select end of document")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
- << 44 << standard.at(0) << standard.at(0).mid(3);
+ << 44 << standard.at(0) << standard.at(0).mid(3)
+ << Qt::Key_Direction_L;
QTest::newRow("select end of block")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
- << 44 << standard.at(0) << standard.at(0).mid(18);
+ << 44 << standard.at(0) << standard.at(0).mid(18)
+ << Qt::Key_Direction_L;
QTest::newRow("delete end of line")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
- << 24 << standard.at(0).mid(0, 24) << QString();
+ << 24 << standard.at(0).mid(0, 24) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("move to start of line")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
- << 0 << standard.at(0) << QString();
+ << 0 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("move to start of block")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
- << 0 << standard.at(0) << QString();
+ << 0 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("move to next char")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12
- << 13 << standard.at(0) << QString();
- QTest::newRow("move to previous char")
+ << 13 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to previous char (ltr)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
- << 2 << standard.at(0) << QString();
- QTest::newRow("select next char")
+ << 2 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to previous char (rtl)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
+ << 4 << standard.at(0) << QString()
+ << Qt::Key_Direction_R;
+ QTest::newRow("move to previous char with selection")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 7
+ << 3 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("select next char (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
+ << 24 << standard.at(0) << standard.at(0).mid(23, 1)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select next char (rtl)")
<< standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
- << 24 << standard.at(0) << standard.at(0).mid(23, 1);
- QTest::newRow("select previous char")
+ << 22 << standard.at(0) << standard.at(0).mid(22, 1)
+ << Qt::Key_Direction_R;
+ QTest::newRow("select previous char (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
+ << 18 << standard.at(0) << standard.at(0).mid(18, 1)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select previous char (rtl)")
<< standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
- << 18 << standard.at(0) << standard.at(0).mid(18, 1);
- QTest::newRow("move to next word")
+ << 20 << standard.at(0) << standard.at(0).mid(19, 1)
+ << Qt::Key_Direction_R;
+ QTest::newRow("move to next word (ltr)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
- << 10 << standard.at(0) << QString();
- QTest::newRow("move to previous word")
+ << 10 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to next word (rtl)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
+ << 4 << standard.at(0) << QString()
+ << Qt::Key_Direction_R;
+ QTest::newRow("move to previous word (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
+ << 4 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to previous word (rlt)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
- << 4 << standard.at(0) << QString();
+ << 10 << standard.at(0) << QString()
+ << Qt::Key_Direction_R;
+ QTest::newRow("select next word")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextWord) << 11 << 11
+ << 16 << standard.at(0) << standard.at(0).mid(11, 5)
+ << Qt::Key_Direction_L;
QTest::newRow("select previous word")
<< standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
- << 10 << standard.at(0) << standard.at(0).mid(10, 1);
+ << 10 << standard.at(0) << standard.at(0).mid(10, 1)
+ << Qt::Key_Direction_L;
QTest::newRow("delete (selection)")
<< standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15
- << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString();
+ << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("delete (no selection)")
<< standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15
- << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString();
+ << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("delete end of word")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24
- << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString();
+ << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("delete start of word")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7
- << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString();
+ << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString()
+ << Qt::Key_Direction_L;
}
void tst_qquicktextedit::keySequence()
@@ -3323,6 +3507,7 @@ void tst_qquicktextedit::keySequence()
QFETCH(int, cursorPosition);
QFETCH(QString, expectedText);
QFETCH(QString, selectedText);
+ QFETCH(Qt::Key, layoutDirection);
if (sequence.isEmpty()) {
QSKIP("Key sequence is undefined");
@@ -3341,6 +3526,8 @@ void tst_qquicktextedit::keySequence()
QTest::qWaitForWindowShown(&canvas);
QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+ simulateKey(&canvas, layoutDirection);
+
textEdit->select(selectionStart, selectionEnd);
simulateKeys(&canvas, sequence);
@@ -3466,7 +3653,7 @@ void tst_qquicktextedit::undo_data()
insertString << " unique instance.";
expectedString << "Ensuring a unique instance.";
- expectedString << "Ensuring a "; // ### Not present in TextInput.
+ expectedString << "Ensuring a "; // ### Not present in TextEdit.
expectedString << "Ensuring an instan";
expectedString << "Ensuring instan";
expectedString << "";
@@ -3754,7 +3941,7 @@ void tst_qquicktextedit::undo_keypressevents_data()
<< "ABC";
expectedString << "ABC";
- // ### One operation in TextInput.
+ // ### One operation in TextEdit.
expectedString << "A";
expectedString << "123";
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index c5db92af45..afe102aa4c 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -63,6 +63,9 @@
#include "../../shared/platforminputcontext.h"
Q_DECLARE_METATYPE(QQuickTextInput::SelectionMode)
+Q_DECLARE_METATYPE(QQuickTextInput::EchoMode)
+Q_DECLARE_METATYPE(Qt::Key)
+
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
@@ -90,6 +93,8 @@ template <typename T> static T evaluate(QObject *scope, const QString &expressio
return result;
}
+template<typename T, int N> int lengthOf(const T (&)[N]) { return N; }
+
typedef QPair<int, QChar> Key;
class tst_qquicktextinput : public QQmlDataTest
@@ -137,6 +142,7 @@ private slots:
void cursorDelegate_data();
void cursorDelegate();
void cursorVisible();
+ void cursorRectangle_data();
void cursorRectangle();
void navigation();
void navigation_RTL();
@@ -145,6 +151,7 @@ private slots:
void canPasteEmpty();
void canPaste();
void readOnly();
+ void focusOnPress();
void openInputPanel();
void setHAlignClearCache();
@@ -185,10 +192,28 @@ private slots:
void QTBUG_19956_data();
void QTBUG_19956_regexp();
+ void implicitSize_data();
+ void implicitSize();
+ void implicitSizeBinding_data();
+ void implicitSizeBinding();
+
void negativeDimensions();
+
+ void setInputMask_data();
+ void setInputMask();
+ void inputMask_data();
+ void inputMask();
+ void clearInputMask();
+ void keypress_inputMask_data();
+ void keypress_inputMask();
+ void hasAcceptableInputMask_data();
+ void hasAcceptableInputMask();
+ void maskCharacter_data();
+ void maskCharacter();
+
private:
- void simulateKey(QQuickView *, int key);
+ void simulateKey(QWindow *, int key);
void simulateKeys(QWindow *window, const QList<Key> &keys);
void simulateKeys(QWindow *window, const QKeySequence &sequence);
@@ -1184,17 +1209,27 @@ void tst_qquicktextinput::mouseSelectionMode_data()
{
QTest::addColumn<QString>("qmlfile");
QTest::addColumn<bool>("selectWords");
+ QTest::addColumn<bool>("focus");
+ QTest::addColumn<bool>("focusOnPress");
// import installed
- QTest::newRow("SelectWords") << testFile("mouseselectionmode_words.qml") << true;
- QTest::newRow("SelectCharacters") << testFile("mouseselectionmode_characters.qml") << false;
- QTest::newRow("default") << testFile("mouseselectionmode_default.qml") << false;
+ QTest::newRow("SelectWords focused") << testFile("mouseselectionmode_words.qml") << true << true << true;
+ QTest::newRow("SelectCharacters focused") << testFile("mouseselectionmode_characters.qml") << false << true << true;
+ QTest::newRow("default focused") << testFile("mouseselectionmode_default.qml") << false << true << true;
+ QTest::newRow("SelectWords unfocused") << testFile("mouseselectionmode_words.qml") << true << false << false;
+ QTest::newRow("SelectCharacters unfocused") << testFile("mouseselectionmode_characters.qml") << false << false << false;
+ QTest::newRow("default unfocused") << testFile("mouseselectionmode_default.qml") << false << true << false;
+ QTest::newRow("SelectWords focuss on press") << testFile("mouseselectionmode_words.qml") << true << false << true;
+ QTest::newRow("SelectCharacters focus on press") << testFile("mouseselectionmode_characters.qml") << false << false << true;
+ QTest::newRow("default focus on press") << testFile("mouseselectionmode_default.qml") << false << false << true;
}
void tst_qquicktextinput::mouseSelectionMode()
{
QFETCH(QString, qmlfile);
QFETCH(bool, selectWords);
+ QFETCH(bool, focus);
+ QFETCH(bool, focusOnPress);
QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -1209,6 +1244,9 @@ void tst_qquicktextinput::mouseSelectionMode()
QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
QVERIFY(textInputObject != 0);
+ textInputObject->setFocus(focus);
+ textInputObject->setFocusOnPress(focusOnPress);
+
// press-and-drag-and-release from x1 to x2
int x1 = 10;
int x2 = 70;
@@ -2126,7 +2164,7 @@ void tst_qquicktextinput::copyAndPaste() {
// copy and paste
QCOMPARE(textInput->text().length(), 12);
- textInput->select(0, textInput->text().length());;
+ textInput->select(0, textInput->text().length());
textInput->copy();
QCOMPARE(textInput->selectedText(), QString("Hello world!"));
QCOMPARE(textInput->selectedText().length(), 12);
@@ -2169,7 +2207,7 @@ void tst_qquicktextinput::copyAndPaste() {
QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
textInput->setEchoMode(echoMode);
textInput->setText("My password");
- textInput->select(0, textInput->text().length());;
+ textInput->select(0, textInput->text().length());
textInput->copy();
if (echoMode == QQuickTextInput::Normal) {
QVERIFY(!clipboard->text().isEmpty());
@@ -2246,7 +2284,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence() {
QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
textInput->setEchoMode(echoMode);
textInput->setText("My password");
- textInput->select(0, textInput->text().length());;
+ textInput->select(0, textInput->text().length());
simulateKeys(&canvas, QKeySequence::Copy);
if (echoMode == QQuickTextInput::Normal) {
QVERIFY(!clipboard->text().isEmpty());
@@ -2402,10 +2440,34 @@ void tst_qquicktextinput::cursorVisible()
QCOMPARE(spy.count(), 7);
}
+void tst_qquicktextinput::cursorRectangle_data()
+{
+ const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
+
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("positionAtWidth");
+ QTest::addColumn<int>("wrapPosition");
+ QTest::addColumn<QString>("shortText");
+ QTest::addColumn<bool>("leftToRight");
+
+ QTest::newRow("left to right")
+ << "Hello World!" << 5 << 11
+ << "Hi"
+ << true;
+ QTest::newRow("right to left")
+ << QString::fromUtf16(arabic_str, lengthOf(arabic_str)) << 5 << 11
+ << QString::fromUtf16(arabic_str, 3)
+ << false;
+}
+
void tst_qquicktextinput::cursorRectangle()
{
- QString text = "Hello World!";
+ QFETCH(QString, text);
+ QFETCH(int, positionAtWidth);
+ QFETCH(int, wrapPosition);
+ QFETCH(QString, shortText);
+ QFETCH(bool, leftToRight);
QQuickTextInput input;
input.setText(text);
@@ -2422,33 +2484,30 @@ void tst_qquicktextinput::cursorRectangle()
QTextLine line = layout.createLine();
layout.endLayout();
- input.setWidth(line.cursorToX(5, QTextLine::Leading));
+ qreal offset = 0;
+ if (leftToRight) {
+ input.setWidth(line.cursorToX(positionAtWidth, QTextLine::Leading));
+ } else {
+ input.setWidth(line.horizontalAdvance() - line.cursorToX(positionAtWidth, QTextLine::Leading));
+ offset = line.horizontalAdvance() - input.width();
+ }
input.setHeight(qCeil(line.height() * 3 / 2));
QRectF r;
- // some tolerance for different fonts.
-#ifdef Q_OS_LINUX
- const int error = 2;
-#else
- const int error = 5;
-#endif
-
- for (int i = 0; i <= 5; ++i) {
+ for (int i = 0; i <= positionAtWidth; ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
- QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
+ QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
// Check the cursor rectangle remains within the input bounding rect when auto scrolling.
- QVERIFY(r.left() < input.width() + error);
- QVERIFY(r.right() >= input.width() - error);
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
- for (int i = 6; i < text.length(); ++i) {
+ for (int i = positionAtWidth + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
QCOMPARE(r, input.cursorRectangle());
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
@@ -2459,7 +2518,11 @@ void tst_qquicktextinput::cursorRectangle()
input.setCursorPosition(i);
r = input.cursorRectangle();
QCOMPARE(r.top(), 0.);
- QVERIFY(r.right() >= 0);
+ if (leftToRight) {
+ QVERIFY(r.right() >= 0);
+ } else {
+ QVERIFY(r.left() <= input.width());
+ }
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -2467,69 +2530,102 @@ void tst_qquicktextinput::cursorRectangle()
// Check position with word wrap.
input.setWrapMode(QQuickTextInput::WordWrap);
input.setAutoScroll(false);
- for (int i = 0; i <= 5; ++i) {
+ for (int i = 0; i < wrapPosition; ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
- QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
+ if (i > positionAtWidth)
+ QEXPECT_FAIL("right to left", "QTBUG-24801", Continue);
+ QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(r.top(), 0.);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
- input.setCursorPosition(6);
+ input.setCursorPosition(wrapPosition);
r = input.cursorRectangle();
- QCOMPARE(r.left(), 0.);
- QVERIFY(r.top() > line.height() - error);
+ if (leftToRight) {
+ QCOMPARE(r.left(), 0.);
+ } else {
+ QCOMPARE(r.left(), input.width());
+ }
+ QVERIFY(r.top() >= line.height() - 1);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
- QCOMPARE(input.positionToRectangle(6), r);
+ QCOMPARE(input.positionToRectangle(11), r);
- for (int i = 7; i < text.length(); ++i) {
+ for (int i = wrapPosition + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.top() > line.height() - error);
+ QVERIFY(r.top() >= line.height() - 1);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
// Check vertical scrolling with word wrap.
input.setAutoScroll(true);
- for (int i = 0; i <= 5; ++i) {
+ for (int i = 0; i <= positionAtWidth; ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
- QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
+ QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(r.top(), 0.);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
- input.setCursorPosition(6);
+ // Whitespace doesn't wrap, so scroll horizontally until the until the cursor
+ // reaches the next non-whitespace character.
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
+ for (int i = positionAtWidth + 1; i < wrapPosition && leftToRight; ++i) {
+ input.setCursorPosition(i);
+ QCOMPARE(r, input.cursorRectangle());
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ QCOMPARE(input.positionToRectangle(i), r);
+ }
+
+ input.setCursorPosition(wrapPosition);
r = input.cursorRectangle();
- QCOMPARE(r.left(), 0.);
- QVERIFY(r.bottom() >= input.height() - error);
+ if (leftToRight) {
+ QCOMPARE(r.left(), 0.);
+ } else {
+ QCOMPARE(r.left(), input.width());
+ }
+ QVERIFY(r.bottom() >= input.height());
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
- QCOMPARE(input.positionToRectangle(6), r);
+ QCOMPARE(input.positionToRectangle(11), r);
- for (int i = 7; i < text.length(); ++i) {
+ for (int i = wrapPosition + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.bottom() >= input.height() - error);
+ QVERIFY(r.bottom() >= input.height());
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
- for (int i = text.length() - 2; i >= 6; --i) {
+ for (int i = text.length() - 2; i >= wrapPosition; --i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.bottom() >= input.height() - error);
+ QVERIFY(r.bottom() >= input.height());
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ QCOMPARE(input.positionToRectangle(i), r);
+ }
+
+ input.setCursorPosition(wrapPosition - 1);
+ r = input.cursorRectangle();
+ QCOMPARE(r.top(), 0.);
+ QEXPECT_FAIL("right to left", "QTBUG-24801", Continue);
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
+ QCOMPARE(input.inputMethodQuery(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);
QCOMPARE(input.positionToRectangle(i), r);
}
- for (int i = 5; i >= 0; --i) {
+ for (int i = positionAtWidth; i >= 0; --i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
QCOMPARE(r.top(), 0.);
@@ -2537,11 +2633,10 @@ void tst_qquicktextinput::cursorRectangle()
QCOMPARE(input.positionToRectangle(i), r);
}
- input.setText("Hi!");
- input.setHAlign(QQuickTextInput::AlignRight);
+ input.setText(shortText);
+ input.setHAlign(leftToRight ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
r = input.cursorRectangle();
- QVERIFY(r.left() < input.width() + error);
- QVERIFY(r.right() >= input.width() - error);
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
}
void tst_qquicktextinput::readOnly()
@@ -2702,7 +2797,7 @@ void tst_qquicktextinput::passwordEchoDelay()
#endif
-void tst_qquicktextinput::simulateKey(QQuickView *view, int key)
+void tst_qquicktextinput::simulateKey(QWindow *view, int key)
{
QKeyEvent press(QKeyEvent::KeyPress, key, 0);
QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
@@ -2712,6 +2807,92 @@ void tst_qquicktextinput::simulateKey(QQuickView *view, int key)
}
+void tst_qquicktextinput::focusOnPress()
+{
+ QString componentStr =
+ "import QtQuick 2.0\n"
+ "TextInput {\n"
+ "property bool selectOnFocus: false\n"
+ "width: 100; height: 50\n"
+ "activeFocusOnPress: true\n"
+ "text: \"Hello World\"\n"
+ "onFocusChanged: { if (focus && selectOnFocus) selectAll() }"
+ " }";
+ QQmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput*>(texteditComponent.create());
+ QVERIFY(textInputObject != 0);
+ QCOMPARE(textInputObject->focusOnPress(), true);
+ QCOMPARE(textInputObject->hasFocus(), false);
+
+ QSignalSpy focusSpy(textInputObject, SIGNAL(focusChanged(bool)));
+ QSignalSpy activeFocusSpy(textInputObject, SIGNAL(focusChanged(bool)));
+ QSignalSpy activeFocusOnPressSpy(textInputObject, SIGNAL(activeFocusOnPressChanged(bool)));
+
+ textInputObject->setFocusOnPress(true);
+ QCOMPARE(textInputObject->focusOnPress(), true);
+ QCOMPARE(activeFocusOnPressSpy.count(), 0);
+
+ QQuickCanvas canvas;
+ canvas.resize(100, 50);
+ textInputObject->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ QCOMPARE(textInputObject->hasFocus(), false);
+ QCOMPARE(textInputObject->hasActiveFocus(), false);
+
+ QPoint centerPoint(canvas.width()/2, canvas.height()/2);
+ Qt::KeyboardModifiers noModifiers = 0;
+ QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(textInputObject->hasFocus(), true);
+ QCOMPARE(textInputObject->hasActiveFocus(), true);
+ QCOMPARE(focusSpy.count(), 1);
+ QCOMPARE(activeFocusSpy.count(), 1);
+ QCOMPARE(textInputObject->selectedText(), QString());
+ QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+
+ textInputObject->setFocusOnPress(false);
+ QCOMPARE(textInputObject->focusOnPress(), false);
+ QCOMPARE(activeFocusOnPressSpy.count(), 1);
+
+ textInputObject->setFocus(false);
+ QCOMPARE(textInputObject->hasFocus(), false);
+ QCOMPARE(textInputObject->hasActiveFocus(), false);
+ QCOMPARE(focusSpy.count(), 2);
+ QCOMPARE(activeFocusSpy.count(), 2);
+
+ // Wait for double click timeout to expire before clicking again.
+ QTest::qWait(400);
+ QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(textInputObject->hasFocus(), false);
+ QCOMPARE(textInputObject->hasActiveFocus(), false);
+ QCOMPARE(focusSpy.count(), 2);
+ QCOMPARE(activeFocusSpy.count(), 2);
+ QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+
+ textInputObject->setFocusOnPress(true);
+ QCOMPARE(textInputObject->focusOnPress(), true);
+ QCOMPARE(activeFocusOnPressSpy.count(), 2);
+
+ // Test a selection made in the on(Active)FocusChanged handler isn't overwritten.
+ textInputObject->setProperty("selectOnFocus", true);
+
+ QTest::qWait(400);
+ QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(textInputObject->hasFocus(), true);
+ QCOMPARE(textInputObject->hasActiveFocus(), true);
+ QCOMPARE(focusSpy.count(), 3);
+ QCOMPARE(activeFocusSpy.count(), 3);
+ QCOMPARE(textInputObject->selectedText(), textInputObject->text());
+ QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+}
+
void tst_qquicktextinput::openInputPanel()
{
PlatformInputContext platformInputContext;
@@ -2888,6 +3069,13 @@ void tst_qquicktextinput::contentSize()
QVERIFY(textObject->contentWidth() > textObject->width());
QVERIFY(textObject->contentHeight() > textObject->height());
QCOMPARE(spy.count(), 3);
+
+ textObject->setText("The quick red fox jumped over the lazy brown dog");
+ for (int w = 60; w < 120; ++w) {
+ textObject->setWidth(w);
+ QVERIFY(textObject->contentWidth() <= textObject->width());
+ QVERIFY(textObject->contentHeight() > textObject->height());
+ }
}
static void sendPreeditText(const QString &text, int cursor)
@@ -4084,63 +4272,135 @@ void tst_qquicktextinput::keySequence_data()
QTest::addColumn<int>("cursorPosition");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QString>("selectedText");
+ QTest::addColumn<QQuickTextInput::EchoMode>("echoMode");
+ QTest::addColumn<Qt::Key>("layoutDirection");
// standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog"
QTest::newRow("select all")
<< standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0
- << 44 << standard.at(0) << standard.at(0);
+ << 44 << standard.at(0) << standard.at(0)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("select start of line")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfLine) << 5 << 5
+ << 0 << standard.at(0) << standard.at(0).mid(0, 5)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("select start of block")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfBlock) << 5 << 5
+ << 0 << standard.at(0) << standard.at(0).mid(0, 5)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("select end of line")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
- << 44 << standard.at(0) << standard.at(0).mid(5);
+ << 44 << standard.at(0) << standard.at(0).mid(5)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("select end of document") // ### Not handled.
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
- << 3 << standard.at(0) << QString();
+ << 3 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("select end of block")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
- << 44 << standard.at(0) << standard.at(0).mid(18);
+ << 44 << standard.at(0) << standard.at(0).mid(18)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("delete end of line")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
- << 24 << standard.at(0).mid(0, 24) << QString();
+ << 24 << standard.at(0).mid(0, 24) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("move to start of line")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
- << 0 << standard.at(0) << QString();
+ << 0 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("move to start of block")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
- << 0 << standard.at(0) << QString();
+ << 0 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("move to next char")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12
- << 13 << standard.at(0) << QString();
- QTest::newRow("move to previous char")
+ << 13 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("move to previous char (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
+ << 2 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("move to previous char (rtl)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
- << 2 << standard.at(0) << QString();
- QTest::newRow("select next char")
+ << 4 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_R;
+ QTest::newRow("move to previous char with selection")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 7
+ << 3 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("select next char (ltr)")
<< standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
- << 24 << standard.at(0) << standard.at(0).mid(23, 1);
- QTest::newRow("select previous char")
+ << 24 << standard.at(0) << standard.at(0).mid(23, 1)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("select next char (rtl)")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
+ << 22 << standard.at(0) << standard.at(0).mid(22, 1)
+ << QQuickTextInput::Normal << Qt::Key_Direction_R;
+ QTest::newRow("select previous char (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
+ << 18 << standard.at(0) << standard.at(0).mid(18, 1)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("select previous char (rtl)")
<< standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
- << 18 << standard.at(0) << standard.at(0).mid(18, 1);
- QTest::newRow("move to next word")
+ << 20 << standard.at(0) << standard.at(0).mid(19, 1)
+ << QQuickTextInput::Normal << Qt::Key_Direction_R;
+ QTest::newRow("move to next word (ltr)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
- << 10 << standard.at(0) << QString();
- QTest::newRow("move to previous word")
+ << 10 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("move to next word (rtl)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
+ << 4 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_R;
+ QTest::newRow("move to next word (password,ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
+ << 44 << standard.at(0) << QString()
+ << QQuickTextInput::Password << Qt::Key_Direction_L;
+ QTest::newRow("move to next word (password,rtl)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
+ << 0 << standard.at(0) << QString()
+ << QQuickTextInput::Password << Qt::Key_Direction_R;
+ QTest::newRow("move to previous word (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
+ << 4 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
+ QTest::newRow("move to previous word (rlt)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
- << 4 << standard.at(0) << QString();
+ << 10 << standard.at(0) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_R;
+ QTest::newRow("move to previous word (password,ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
+ << 0 << standard.at(0) << QString()
+ << QQuickTextInput::Password << Qt::Key_Direction_L;
+ QTest::newRow("move to previous word (password,rtl)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
+ << 44 << standard.at(0) << QString()
+ << QQuickTextInput::Password << Qt::Key_Direction_R;
+ QTest::newRow("select next word")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextWord) << 11 << 11
+ << 16 << standard.at(0) << standard.at(0).mid(11, 5)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("select previous word")
<< standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
- << 10 << standard.at(0) << standard.at(0).mid(10, 1);
+ << 10 << standard.at(0) << standard.at(0).mid(10, 1)
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("delete (selection)")
<< standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15
- << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString();
+ << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("delete (no selection)")
<< standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15
- << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString();
+ << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("delete end of word")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24
- << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString();
+ << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
QTest::newRow("delete start of word")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7
- << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString();
+ << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString()
+ << QQuickTextInput::Normal << Qt::Key_Direction_L;
}
void tst_qquicktextinput::keySequence()
@@ -4152,6 +4412,8 @@ void tst_qquicktextinput::keySequence()
QFETCH(int, cursorPosition);
QFETCH(QString, expectedText);
QFETCH(QString, selectedText);
+ QFETCH(QQuickTextInput::EchoMode, echoMode);
+ QFETCH(Qt::Key, layoutDirection);
if (sequence.isEmpty()) {
QSKIP("Key sequence is undefined");
@@ -4162,6 +4424,7 @@ void tst_qquicktextinput::keySequence()
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
QVERIFY(textInput != 0);
+ textInput->setEchoMode(echoMode);
QQuickCanvas canvas;
textInput->setParentItem(canvas.rootItem());
@@ -4170,6 +4433,8 @@ void tst_qquicktextinput::keySequence()
QTest::qWaitForWindowShown(&canvas);
QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+ simulateKey(&canvas, layoutDirection);
+
textInput->select(selectionStart, selectionEnd);
simulateKeys(&canvas, sequence);
@@ -4507,9 +4772,6 @@ void tst_qquicktextinput::undo_keypressevents_data()
<< Qt::Key_Delete
<< QKeySequence::Undo
<< Qt::Key_Right
-#ifdef Q_OS_WIN //Mac(?) has a specialcase to handle jumping to the end of a selection
- << Qt::Key_Left
-#endif
<< (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
<< Qt::Key_Delete;
@@ -4586,6 +4848,19 @@ void tst_qquicktextinput::undo_keypressevents_data()
expectedString << "123";
QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting '123'
+ keys << "123"
+ << QKeySequence::Undo
+ << QKeySequence::Redo;
+
+ expectedString << "123";
+ expectedString << QString();
+
+ QTest::newRow("Insert,undo,redo") << keys << expectedString;
}
}
@@ -4683,6 +4958,58 @@ void tst_qquicktextinput::QTBUG_19956_regexp()
QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
}
+void tst_qquicktextinput::implicitSize_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("wrap");
+ QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextInput.NoWrap";
+ QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextInput.Wrap";
+}
+
+void tst_qquicktextinput::implicitSize()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, wrap);
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
+
+ QVERIFY(textObject->width() < textObject->implicitWidth());
+ QVERIFY(textObject->height() == textObject->implicitHeight());
+
+ textObject->resetWidth();
+ QVERIFY(textObject->width() == textObject->implicitWidth());
+ QVERIFY(textObject->height() == textObject->implicitHeight());
+}
+
+void tst_qquicktextinput::implicitSizeBinding_data()
+{
+ implicitSize_data();
+}
+
+void tst_qquicktextinput::implicitSizeBinding()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, wrap);
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + " }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickTextInput *textObject = qobject_cast<QQuickTextInput *>(object.data());
+
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetWidth();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetHeight();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+}
+
void tst_qquicktextinput::negativeDimensions()
{
@@ -4696,6 +5023,482 @@ void tst_qquicktextinput::negativeDimensions()
QCOMPARE(input->height(), qreal(-1));
}
+
+void tst_qquicktextinput::setInputMask_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("expectedDisplay");
+ QTest::addColumn<bool>("insert_text");
+
+ // both keyboard and insert()
+ for (int i=0; i<2; i++) {
+ bool insert_text = i==0 ? false : true;
+ QString insert_mode = "keys ";
+ if (insert_text)
+ insert_mode = "insert ";
+
+ QTest::newRow(QString(insert_mode + "ip_localhost").toLatin1())
+ << QString("000.000.000.000")
+ << QString("127.0.0.1")
+ << QString("127.0.0.1")
+ << QString("127.0 .0 .1 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "mac").toLatin1())
+ << QString("HH:HH:HH:HH:HH:HH;#")
+ << QString("00:E0:81:21:9E:8E")
+ << QString("00:E0:81:21:9E:8E")
+ << QString("00:E0:81:21:9E:8E")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "mac2").toLatin1())
+ << QString("<HH:>HH:!HH:HH:HH:HH;#")
+ << QString("AAe081219E8E")
+ << QString("aa:E0:81:21:9E:8E")
+ << QString("aa:E0:81:21:9E:8E")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "byte").toLatin1())
+ << QString("BBBBBBBB;0")
+ << QString("11011001")
+ << QString("11111")
+ << QString("11011001")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "halfbytes").toLatin1())
+ << QString("bbbb.bbbb;-")
+ << QString("110. 0001")
+ << QString("110.0001")
+ << QString("110-.0001")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "blank char same type as content").toLatin1())
+ << QString("000.000.000.000;0")
+ << QString("127.0.0.1")
+ << QString("127...1")
+ << QString("127.000.000.100")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "parts of ip_localhost").toLatin1())
+ << QString("000.000.000.000")
+ << QString(".0.0.1")
+ << QString(".0.0.1")
+ << QString(" .0 .0 .1 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "ip_null").toLatin1())
+ << QString("000.000.000.000")
+ << QString()
+ << QString("...")
+ << QString(" . . . ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "ip_null_hash").toLatin1())
+ << QString("000.000.000.000;#")
+ << QString()
+ << QString("...")
+ << QString("###.###.###.###")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "ip_overflow").toLatin1())
+ << QString("000.000.000.000")
+ << QString("1234123412341234")
+ << QString("123.412.341.234")
+ << QString("123.412.341.234")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "uppercase").toLatin1())
+ << QString(">AAAA")
+ << QString("AbCd")
+ << QString("ABCD")
+ << QString("ABCD")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "lowercase").toLatin1())
+ << QString("<AAAA")
+ << QString("AbCd")
+ << QString("abcd")
+ << QString("abcd")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "nocase").toLatin1())
+ << QString("!AAAA")
+ << QString("AbCd")
+ << QString("AbCd")
+ << QString("AbCd")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "nocase1").toLatin1())
+ << QString("!A!A!A!A")
+ << QString("AbCd")
+ << QString("AbCd")
+ << QString("AbCd")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "nocase2").toLatin1())
+ << QString("AAAA")
+ << QString("AbCd")
+ << QString("AbCd")
+ << QString("AbCd")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "reserved").toLatin1())
+ << QString("{n}[0]")
+ << QString("A9")
+ << QString("A9")
+ << QString("A9")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "escape01").toLatin1())
+ << QString("\\\\N\\\\n00")
+ << QString("9")
+ << QString("Nn9")
+ << QString("Nn9 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "escape02").toLatin1())
+ << QString("\\\\\\\\00")
+ << QString("0")
+ << QString("\\0")
+ << QString("\\0 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "escape03").toLatin1())
+ << QString("\\\\(00\\\\)")
+ << QString("0")
+ << QString("(0)")
+ << QString("(0 )")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "upper_lower_nocase1").toLatin1())
+ << QString(">AAAA<AAAA!AAAA")
+ << QString("AbCdEfGhIjKl")
+ << QString("ABCDefghIjKl")
+ << QString("ABCDefghIjKl")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "upper_lower_nocase2").toLatin1())
+ << QString(">aaaa<aaaa!aaaa")
+ << QString("AbCdEfGhIjKl")
+ << QString("ABCDefghIjKl")
+ << QString("ABCDefghIjKl")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "exact_case1").toLatin1())
+ << QString(">A<A<A>A>A<A!A!A")
+ << QString("AbCdEFGH")
+ << QString("AbcDEfGH")
+ << QString("AbcDEfGH")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case2").toLatin1())
+ << QString(">A<A<A>A>A<A!A!A")
+ << QString("aBcDefgh")
+ << QString("AbcDEfgh")
+ << QString("AbcDEfgh")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case3").toLatin1())
+ << QString(">a<a<a>a>a<a!a!a")
+ << QString("AbCdEFGH")
+ << QString("AbcDEfGH")
+ << QString("AbcDEfGH")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case4").toLatin1())
+ << QString(">a<a<a>a>a<a!a!a")
+ << QString("aBcDefgh")
+ << QString("AbcDEfgh")
+ << QString("AbcDEfgh")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case5").toLatin1())
+ << QString(">H<H<H>H>H<H!H!H")
+ << QString("aBcDef01")
+ << QString("AbcDEf01")
+ << QString("AbcDEf01")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case6").toLatin1())
+ << QString(">h<h<h>h>h<h!h!h")
+ << QString("aBcDef92")
+ << QString("AbcDEf92")
+ << QString("AbcDEf92")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "illegal_keys1").toLatin1())
+ << QString("AAAAAAAA")
+ << QString("A2#a;.0!")
+ << QString("Aa")
+ << QString("Aa ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "illegal_keys2").toLatin1())
+ << QString("AAAA")
+ << QString("f4f4f4f4")
+ << QString("ffff")
+ << QString("ffff")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "blank=input").toLatin1())
+ << QString("9999;0")
+ << QString("2004")
+ << QString("2004")
+ << QString("2004")
+ << bool(insert_text);
+ }
+}
+
+void tst_qquicktextinput::setInputMask()
+{
+ QFETCH(QString, mask);
+ QFETCH(QString, input);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, expectedDisplay);
+ QFETCH(bool, insert_text);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ // then either insert using insert() or keyboard
+ if (insert_text) {
+ textInput->insert(0, input);
+ } else {
+ QQuickCanvas canvas;
+ textInput->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ simulateKey(&canvas, Qt::Key_Home);
+ for (int i = 0; i < input.length(); i++)
+ QTest::keyClick(&canvas, input.at(i).toLatin1());
+ }
+
+ QEXPECT_FAIL( "keys blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
+ QEXPECT_FAIL( "insert blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
+
+ QCOMPARE(textInput->text(), expectedText);
+ QCOMPARE(textInput->displayText(), expectedDisplay);
+}
+
+void tst_qquicktextinput::inputMask_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<QString>("expectedMask");
+
+ // if no mask is set a nul string should be returned
+ QTest::newRow("nul 1") << QString("") << QString();
+ QTest::newRow("nul 2") << QString() << QString();
+
+ // try different masks
+ QTest::newRow("mask 1") << QString("000.000.000.000") << QString("000.000.000.000; ");
+ QTest::newRow("mask 2") << QString("000.000.000.000;#") << QString("000.000.000.000;#");
+ QTest::newRow("mask 3") << QString("AAA.aa.999.###;") << QString("AAA.aa.999.###; ");
+ QTest::newRow("mask 4") << QString(">abcdef<GHIJK") << QString(">abcdef<GHIJK; ");
+
+ // set an invalid input mask...
+ // the current behaviour is that this exact (faulty) string is returned.
+ QTest::newRow("invalid") << QString("ABCDEFGHIKLMNOP;") << QString("ABCDEFGHIKLMNOP; ");
+
+ // verify that we can unset the mask again
+ QTest::newRow("unset") << QString("") << QString();
+}
+
+void tst_qquicktextinput::inputMask()
+{
+ QFETCH(QString, mask);
+ QFETCH(QString, expectedMask);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QCOMPARE(textInput->inputMask(), expectedMask);
+}
+
+void tst_qquicktextinput::clearInputMask()
+{
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"000.000.000.000\" }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QVERIFY(textInput->inputMask() != QString());
+ textInput->setInputMask(QString());
+ QCOMPARE(textInput->inputMask(), QString());
+}
+
+void tst_qquicktextinput::keypress_inputMask_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<KeyList>("keys");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("expectedDisplayText");
+
+ {
+ KeyList keys;
+ // inserting 'A1.2B'
+ keys << Qt::Key_Home << "A1.2B";
+ QTest::newRow("jumping on period(separator)") << QString("000.000;_") << keys << QString("1.2") << QString("1__.2__");
+ }
+ {
+ KeyList keys;
+ // inserting '0!P3'
+ keys << Qt::Key_Home << "0!P3";
+ QTest::newRow("jumping on input") << QString("D0.AA.XX.AA.00;_") << keys << QString("0..!P..3") << QString("_0.__.!P.__.3_");
+ }
+ {
+ KeyList keys;
+ // pressing delete
+ keys << Qt::Key_Home
+ << Qt::Key_Delete;
+ QTest::newRow("delete") << QString("000.000;_") << keys << QString(".") << QString("___.___");
+ }
+ {
+ KeyList keys;
+ // selecting all and delete
+ keys << Qt::Key_Home
+ << Key(Qt::ShiftModifier, Qt::Key_End)
+ << Qt::Key_Delete;
+ QTest::newRow("deleting all") << QString("000.000;_") << keys << QString(".") << QString("___.___");
+ }
+ {
+ KeyList keys;
+ // inserting '12.12' then two backspaces
+ keys << Qt::Key_Home << "12.12" << Qt::Key_Backspace << Qt::Key_Backspace;
+ QTest::newRow("backspace") << QString("000.000;_") << keys << QString("12.") << QString("12_.___");
+ }
+ {
+ KeyList keys;
+ // inserting '12ab'
+ keys << Qt::Key_Home << "12ab";
+ QTest::newRow("uppercase") << QString("9999 >AA;_") << keys << QString("12 AB") << QString("12__ AB");
+ }
+}
+
+void tst_qquicktextinput::keypress_inputMask()
+{
+ QFETCH(QString, mask);
+ QFETCH(KeyList, keys);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, expectedDisplayText);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QQuickCanvas canvas;
+ textInput->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ simulateKeys(&canvas, keys);
+
+ QCOMPARE(textInput->text(), expectedText);
+ QCOMPARE(textInput->displayText(), expectedDisplayText);
+}
+
+
+void tst_qquicktextinput::hasAcceptableInputMask_data()
+{
+ QTest::addColumn<QString>("optionalMask");
+ QTest::addColumn<QString>("requiredMask");
+ QTest::addColumn<QString>("invalid");
+ QTest::addColumn<QString>("valid");
+
+ QTest::newRow("Alphabetic optional and required")
+ << QString("aaaa") << QString("AAAA") << QString("ab") << QString("abcd");
+ QTest::newRow("Alphanumeric optional and require")
+ << QString("nnnn") << QString("NNNN") << QString("R2") << QString("R2D2");
+ QTest::newRow("Any optional and required")
+ << QString("xxxx") << QString("XXXX") << QString("+-") << QString("+-*/");
+ QTest::newRow("Numeric (0-9) required")
+ << QString("0000") << QString("9999") << QString("11") << QString("1138");
+ QTest::newRow("Numeric (1-9) optional and required")
+ << QString("dddd") << QString("DDDD") << QString("12") << QString("1234");
+}
+
+void tst_qquicktextinput::hasAcceptableInputMask()
+{
+ QFETCH(QString, optionalMask);
+ QFETCH(QString, requiredMask);
+ QFETCH(QString, invalid);
+ QFETCH(QString, valid);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + optionalMask + "\" }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QQuickCanvas canvas;
+ textInput->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ // test that invalid input (for required) work for optionalMask
+ textInput->setText(invalid);
+ QVERIFY(textInput->hasAcceptableInput());
+
+ // at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless
+ QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort);
+
+ // test requiredMask
+ textInput->setInputMask(requiredMask);
+ textInput->setText(invalid);
+ QVERIFY(!textInput->hasAcceptableInput());
+
+ textInput->setText(valid);
+ QVERIFY(textInput->hasAcceptableInput());
+}
+
+void tst_qquicktextinput::maskCharacter_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<bool>("expectedValid");
+
+ QTest::newRow("Hex") << QString("H")
+ << QString("0123456789abcdefABCDEF") << true;
+ QTest::newRow("hex") << QString("h")
+ << QString("0123456789abcdefABCDEF") << true;
+ QTest::newRow("HexInvalid") << QString("H")
+ << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ")
+ << false;
+ QTest::newRow("hexInvalid") << QString("h")
+ << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ")
+ << false;
+ QTest::newRow("Bin") << QString("B")
+ << QString("01") << true;
+ QTest::newRow("bin") << QString("b")
+ << QString("01") << true;
+ QTest::newRow("BinInvalid") << QString("B")
+ << QString("23456789qwertyuiopasdfghjklzxcvbnm")
+ << false;
+ QTest::newRow("binInvalid") << QString("b")
+ << QString("23456789qwertyuiopasdfghjklzxcvbnm")
+ << false;
+}
+
+void tst_qquicktextinput::maskCharacter()
+{
+ QFETCH(QString, mask);
+ QFETCH(QString, input);
+ QFETCH(bool, expectedValid);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QQuickCanvas canvas;
+ textInput->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ for (int i = 0; i < input.size(); ++i) {
+ QString in = QString(input.at(i));
+ QString expected = expectedValid ? in : QString();
+ textInput->setText(QString(input.at(i)));
+ QCOMPARE(textInput->text(), expected);
+ }
+}
+
QTEST_MAIN(tst_qquicktextinput)
#include "tst_qquicktextinput.moc"
diff --git a/tests/system/sys_listview.qtt b/tests/system/sys_listview.qtt
new file mode 100644
index 0000000000..efd116fa92
--- /dev/null
+++ b/tests/system/sys_listview.qtt
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=qtdeclarative
+
+testcase = {
+
+ altering_listview_primary_properties: function()
+ {
+ // Test Meta-data
+ testTitle = "Altering ListView primary properties";
+ testBinary = "alteredViews.qml";
+ testSource: "$QTDIR/qtdeclarative/tests/system/listview";
+ testGoal = "Verify that the model and delegate for a ListView can be changed";
+ testPreconditions = "None";
+ testGroups = "BAT,QtQuick 2.0";
+
+ // Test Steps
+ prompt(twiki('---+++ ' + testTitle + '<br><br>
+ *Goal:* ' + testGoal + '<br>
+ *Pre-Requisites:* ' + testPreconditions + '<br>
+ *Tested Binary:* ' + testBinary + '<br>
+ | *Step* | *Verification* |
+ | Run '+testBinary+' | Application has started, showing a ListView |
+ | | The view shows items named Model1_1 - 5, and the delegates are white with a black border |
+ | Press the Mod button | The view now shows items named Model2_1 - 5 |
+ | Press Del | The delegates are now golden with a black border |
+ | Press Mod, then Del | The view again shows items named Model1_1 - 5, and are white |'));
+ },
+
+ altering_listview_orientation: function()
+ {
+ // Test Meta-data
+ testTitle = "Altering ListView orientation";
+ testBinary = "alteredViews.qml";
+ testSource: "$QTDIR/qtdeclarative/tests/system/listview";
+ testGoal = "Verify that the orientation of a listview can be changed at runtime";
+ testPreconditions = "None";
+ testGroups = "BAT,QtQuick 2.0";
+
+ // Test Steps
+ prompt(twiki('---+++ ' + testTitle + '<br><br>
+ *Goal:* ' + testGoal + '<br>
+ *Pre-Requisites:* ' + testPreconditions + '<br>
+ *Tested Binary:* ' + testBinary + '<br>
+ | *Step* | *Verification* |
+ | Run '+testBinary+' | Application has started, showing a ListView |
+ | | The view shows items named Model1_1 - 5, and the delegates are white with a black border |
+ | Press the Ori button | The view is now displayed in a horizontal orientation |
+ | | The delegates should have resized quickly and smoothly, and the text rotated anticlockwise (both animated) |
+ | Press Del | The delegates are now golden with a black border, still in horizontal orientation |
+ | Press Ori | The view again shows in a vertical orientation, with the golden delegates |'));
+ },
+
+ basic_view_transition: function()
+ {
+ // Test Meta-data
+ testTitle = "Basic View Transitions";
+ testBinary = "viewTransitions.qml";
+ testSource: "$QTDIR/qtdeclarative/tests/system/listview";
+ testGoal = "Verify a basic transition can be applied to a ListView action";
+ testPreconditions = "None";
+ testGroups = "BAT,QtQuick 2.0";
+ testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views";
+
+ // Test Steps
+ prompt(twiki('---+++ ' + testTitle + '<br><br>
+ *Goal:* ' + testGoal + '<br>
+ *Pre-Requisites:* ' + testPreconditions + '<br>
+ *Tested Binary:* ' + testBinary + '<br>
+ | *Step* | *Verification* |
+ | Run '+testBinary+' | Application has started, showing a ListView |
+ | Press the Set A button | The Set A button shows green |
+ | Press Add | A new yellow item fades in after the currently selected item |
+ | | The other items slide down, with a slight delay for each item, giving it a flowing effect |
+ | Select the new item | |
+ | Press To Top | The item changes to light blue and moves to the top, curving out to the right of the ListView |
+ | Select an item near the top and press Remove | The selected item fades out |
+ | | The other items slide up, with a slight delay for each item, giving it a flowing effect |'));
+ },
+
+ switching_view_transition: function() {
+ // Test Meta-data
+ testTitle = "Switching View Transitions";
+ testBinary = "viewTransitions.qml";
+ testSource: "$QTDIR/qtdeclarative/tests/system/listview";
+ testGoal = "Verify a basic ListView transition can be changed to another";
+ testPreconditions = "None";
+ testGroups = "BAT,QtQuick 2.0";
+ testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views";
+
+ // Test Steps
+ prompt(twiki('---+++ ' + testTitle + '<br><br>
+ *Goal:* ' + testGoal + '<br>
+ *Pre-Requisites:* ' + testPreconditions + '<br>
+ *Tested Binary:* ' + testBinary + '<br>
+ | *Step* | *Verification* |
+ | Run '+testBinary+' | Application has started, showing a ListView |
+ | Press the Set A button | The Set A button shows green |
+ | Press Add | A new yellow item fades in after the currently selected item |
+ | | The other items slide down, with a slight delay for each item, giving it a flowing effect |
+ | Select the new item | |
+ | Press To Top | The item changes to light blue and moves to the top, curving out to the right of the ListView |
+ | Select an item near the top and press Remove | The selected item fades out |
+ | | The other items slide up, with a slight delay for each item, giving it a flowing effect |
+ | Press the Set B button | The Set B button shows green |
+ | Press Add | A new yellow item pops in after the currently selected item |
+ | | The other items tumble down in a disorderly manner |
+ | Select the new item | |
+ | Press To Top | The item changes from red to light blue and curves out to the right of the ListView, bouncing in at the top |
+ | Select an item near the top and press Remove | The selected item pops out |
+ | | The other items slide up, with a slight delay for each item, giving it a flowing effect |'));
+ },
+
+ different_transitions_for_every_operation: function() {
+ // Test Meta-data
+ testTitle = "Different Transitions for all Operations";
+ testBinary = "viewTransitions.qml";
+ testSource: "$QTDIR/qtdeclarative/tests/system/listview";
+ testGoal = "Verify a different Transition can be applied to displacement from adding, moving and removing.";
+ testPreconditions = "None";
+ testGroups = "BAT,QtQuick 2.0";
+ testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views";
+
+ // Test Steps
+ prompt(twiki('---+++ ' + testTitle + '<br><br>
+ *Goal:* ' + testGoal + '<br>
+ *Pre-Requisites:* ' + testPreconditions + '<br>
+ *Tested Binary:* ' + testBinary + '<br>
+ | *Step* | *Verification* |
+ | Run '+testBinary+' | Application has started, showing a ListView |
+ | Press the Set C button | The Set C button shows green |
+ | Press Add | A new yellow item swoops in from the side |
+ | | The other items jitter down, with a slight delay for each item |
+ | Select the new item | |
+ | Press To Top | The item changes from red to light blue and moves to the top, curving out to the right of the ListView |
+ | | The other items bounce down in a solid block |
+ | Select an item near the top and press Remove | The selected item fades out in a flashing manner |
+ | | The other items snap up, with a slight delay for each item |
+ | Press the Append button a few times | Each added item swoops in from alternating sides | '));
+ },
+
+ delegates_and_effects: function() {
+ testTitle = "Delegates and effects";
+ testBinary = "viewTransitions.qml";
+ testSource: "$QTDIR/qtdeclarative/tests/system/listview";
+ testGoal = "Verify a delegate in transition can show effects.";
+ testPreconditions = "None";
+ testGroups = "BAT,QtQuick 2.0";
+ testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views";
+
+ // Test Steps
+ prompt(twiki('---+++ ' + testTitle + '<br><br>
+ *Goal:* ' + testGoal + '<br>
+ *Pre-Requisites:* ' + testPreconditions + '<br>
+ *Tested Binary:* ' + testBinary + '<br>
+ | *Step* | *Verification* |
+ | Run '+testBinary+' | Application has started, showing a ListView |
+ | Press the Set D button | The Set D button shows green |
+ | Select a lower item | The item is highlighted |
+ | Press To Top | The item fades to red particles, shifts to the top, and fades back to a normal delegate |
+ | | The other items shuffle down |'));
+ },
+
+ attached_onremove_property: function() {
+ testTitle = "Using the attached onRemove property";
+ testBinary = "onRemove.qml";
+ testSource: "$QTDIR/qtdeclarative/tests/system/listview";
+ testGoal = "Verify the onRemove attached property can be assigned.";
+ testPreconditions = "None";
+ testGroups = "BAT,QtQuick 2.0";
+ testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views";
+
+ // Test Steps
+ prompt(twiki('---+++ ' + testTitle + '<br><br>
+ *Goal:* ' + testGoal + '<br>
+ *Pre-Requisites:* ' + testPreconditions + '<br>
+ *Tested Binary:* ' + testBinary + '<br>
+ | *Step* | *Verification* |
+ | Run '+testBinary+' | Application has started, showing a ListView |
+ | Press the <b>-</b> button | The selected item disappears in a shower of sparks |'));
+ }
+}
diff --git a/tests/testapplications/listview/alteredViews.qml b/tests/testapplications/listview/alteredViews.qml
new file mode 100644
index 0000000000..26aa678db2
--- /dev/null
+++ b/tests/testapplications/listview/alteredViews.qml
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 300
+ height: 400
+
+ ListView {
+ id: listview
+ model: model1
+ delegate: delegate1
+ anchors.fill: parent
+ anchors.margins: 20
+ }
+
+ Component {
+ id: delegate1
+ Rectangle {
+ height: listview.orientation == ListView.Horizontal ? 260 : 50
+ Behavior on height { NumberAnimation { duration: 500 } }
+ width: listview.orientation == ListView.Horizontal ? 50 : 260
+ Behavior on width { NumberAnimation { duration: 500 } }
+ border.color: "black"
+ Text {
+ anchors.centerIn: parent; color: "black"; text: model.name
+ rotation: listview.orientation == ListView.Horizontal ? -90 : 0
+ Behavior on rotation { NumberAnimation { duration: 500 } }
+
+ }
+ }
+ }
+
+ Component {
+ id: delegate2
+ Rectangle {
+ height: listview.orientation == ListView.Horizontal ? 260 : 50
+ Behavior on height { NumberAnimation { duration: 500 } }
+ width: listview.orientation == ListView.Horizontal ? 50 : 260
+ Behavior on width { NumberAnimation { duration: 500 } }
+ color: "goldenrod"; border.color: "black"
+ Text {
+ anchors.centerIn: parent; color: "royalblue"; text: model.name
+ rotation: listview.orientation == ListView.Horizontal ? -90 : 0
+ Behavior on rotation { NumberAnimation { duration: 1500 } }
+ }
+ }
+
+ }
+
+ Column {
+ Rectangle {
+ height: 50
+ width: 50
+ color: "blue"
+ border.color: "orange"
+ Text {
+ anchors.centerIn: parent
+ text: "Mod"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: listview.model = listview.model == model2 ? model1 : model2
+ }
+ }
+
+ Rectangle {
+ height: 50
+ width: 50
+ color: "blue"
+ border.color: "orange"
+ Text {
+ anchors.centerIn: parent
+ text: "Del"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: listview.delegate = listview.delegate == delegate2 ? delegate1 : delegate2
+ }
+ }
+
+ Rectangle {
+ height: 50
+ width: 50
+ color: "blue"
+ border.color: "orange"
+ Text {
+ anchors.centerIn: parent
+ text: "Ori"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: listview.orientation = listview.orientation == ListView.Horizontal ? ListView.Vertical : ListView.Horizontal
+ }
+ }
+ }
+
+ ListModel {
+ id: model1
+ ListElement { name: "model1_1" }
+ ListElement { name: "model1_2" }
+ ListElement { name: "model1_3" }
+ ListElement { name: "model1_4" }
+ ListElement { name: "model1_5" }
+ }
+
+ ListModel {
+ id: model2
+ ListElement { name: "model2_1" }
+ ListElement { name: "model2_2" }
+ ListElement { name: "model2_3" }
+ ListElement { name: "model2_4" }
+ ListElement { name: "model2_5" }
+ }
+}
diff --git a/tests/testapplications/listview/onRemove.qml b/tests/testapplications/listview/onRemove.qml
new file mode 100644
index 0000000000..2c1d52a40e
--- /dev/null
+++ b/tests/testapplications/listview/onRemove.qml
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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.Particles 2.0
+Item {
+ id: root
+ width: 450; height: 600
+
+ Component {
+ id: viewDelegate
+
+ Rectangle {
+ id: item
+ signal boom
+ Connections {
+ target: item
+ onBoom: emitter.burst(1000)
+ }
+
+ width: 225; height: 40
+ border.width: ListView.isCurrentItem ? 3 : 1
+ z: ListView.isCurrentItem ? 100 : 1
+ color: original ? "lightsteelblue" : "yellow"
+ objectName: name
+ Text { x: 10; text: name; font.pixelSize: 20 }
+ MouseArea { anchors.fill: parent; onClicked: listview.currentIndex = index }
+
+ Emitter {
+ id: emitter
+ system: ps
+ anchors.fill: parent
+ enabled: false
+ speed: AngleDirection {
+ angle: 0
+ angleVariation: 360
+ magnitude: 50
+ magnitudeVariation: 50
+ }
+ lifeSpan: 2000
+ }
+
+ ListView.onRemove: SequentialAnimation {
+ PropertyAction { target: item; property: "ListView.delayRemove"; value: true }
+ PropertyAction { target: item; property: "opacity"; value: 0 }
+ ScriptAction { script: item.boom() }
+ PauseAnimation { duration: 1000 }
+ PropertyAction { target: item; property: "ListView.delayRemove"; value: false }
+ }
+ }
+ }
+
+
+ ListView {
+ id: listview
+ width: 225; height: 500
+ anchors.centerIn: parent
+ delegate: viewDelegate
+ header: Rectangle {
+ height: 50; width: 225
+ color: "blue"
+ Text { anchors.centerIn: parent; text: "Transitions!"; color: "goldenrod" }
+ }
+ model: ListModel {
+ id: a_model
+ ListElement { name: "Item A"; original: true }
+ ListElement { name: "Item B"; original: true }
+ ListElement { name: "Item C"; original: true }
+ ListElement { name: "Item D"; original: true }
+ ListElement { name: "Item E"; original: true }
+ ListElement { name: "Item F"; original: true }
+ }
+ Rectangle {
+ anchors.fill: parent
+ color: "transparent"
+ border.color: "black"
+ }
+
+ }
+
+ ParticleSystem {
+ id: ps
+ ImageParticle {
+ id: imageparticle
+ source: "star.png"
+ color: "blue"
+ }
+ }
+ Column {
+ spacing: 2
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 25; font.bold: true }
+ MouseArea { anchors.fill: parent; onClicked: listview.model.insert(listview.currentIndex+1, {"name": "New item", "original": false } ) }
+ }
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "-"; font.pixelSize: 25; font.bold: true }
+ MouseArea { anchors.fill: parent; onClicked: listview.model.remove(listview.currentIndex) }
+ }
+ }
+}
+
+
+
diff --git a/tests/testapplications/listview/star.png b/tests/testapplications/listview/star.png
new file mode 100644
index 0000000000..0d592cfa87
--- /dev/null
+++ b/tests/testapplications/listview/star.png
Binary files differ
diff --git a/tests/testapplications/listview/viewTransitions.qml b/tests/testapplications/listview/viewTransitions.qml
new file mode 100644
index 0000000000..6ed7cc1619
--- /dev/null
+++ b/tests/testapplications/listview/viewTransitions.qml
@@ -0,0 +1,479 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** 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 Nokia Corporation and its Subsidiary(-ies) 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.Particles 2.0
+Item {
+ id: root
+ width: 450; height: 600
+
+ property int currentSet: 0
+ property bool useStock: false
+
+ Component {
+ id: viewDelegate
+
+ Rectangle {
+ id: item
+ property bool movn: false
+ property int parts: 0
+
+ width: 225; height: 40
+ border.width: ListView.isCurrentItem ? 3 : 1
+ z: ListView.isCurrentItem ? 100 : 1
+ color: original ? "lightsteelblue" : "yellow"
+ objectName: name
+ Text { x: 10; text: name; font.pixelSize: 20 }
+ MouseArea { anchors.fill: parent; onClicked: listview.currentIndex = index }
+
+ Emitter {
+ id: emitter
+ system: ps
+ anchors.fill: parent
+ enabled: false
+ speed: AngleDirection {
+ angle: 0
+ angleVariation: 360
+ magnitude: 50
+ magnitudeVariation: 50
+ }
+ }
+ Emitter {
+ id: emitter2
+ system: ps
+ anchors.fill: parent
+ enabled: item.movn
+ emitRate: parts
+ speed: AngleDirection {
+ angle: 0
+ angleVariation: 360
+ magnitude: 2
+ magnitudeVariation: 5
+ }
+ }
+ }
+ }
+
+ ListView {
+ id: listview
+ width: 225; height: 500
+ anchors.centerIn: parent
+ delegate: viewDelegate
+ header: Rectangle {
+ height: 50; width: 225
+ color: "blue"
+ Text { anchors.centerIn: parent; text: "Transitions!"; color: "goldenrod" }
+ }
+ model: ListModel {
+ id: a_model
+ ListElement { name: "Item A"; original: true }
+ ListElement { name: "Item B"; original: true }
+ ListElement { name: "Item C"; original: true }
+ ListElement { name: "Item D"; original: true }
+ ListElement { name: "Item E"; original: true }
+ ListElement { name: "Item F"; original: true }
+ }
+ Rectangle {
+ anchors.fill: parent
+ color: "transparent"
+ border.color: "black"
+ }
+
+ }
+
+ ParticleSystem {
+ id: ps
+ ImageParticle {
+ id: imageparticle
+ source: "star.png"
+ color: "red"
+ }
+ }
+
+
+ /* States (Selected operation Transitions) */
+ states: [
+ State {
+ name: "setA"
+ when: currentSet == 0
+ PropertyChanges {
+ target: listview
+ add: a_add
+ move: a_move
+ remove: a_remove
+ displaced: a_displaced
+ }
+ },
+ State {
+ name: "setB"
+ when: currentSet == 1
+ PropertyChanges {
+ target: listview
+ add: b_add
+ move: b_move
+ remove: b_remove
+ displaced: b_displaced
+ }
+ },
+ State {
+ name: "setC"
+ when: currentSet == 2
+ PropertyChanges {
+ target: listview
+ add: c_add
+ move: c_move
+ remove: c_remove
+ addDisplaced: c_addDisplaced
+ moveDisplaced: c_moveDisplaced
+ removeDisplaced: c_removeDisplaced
+ }
+ },
+ State {
+ name: "setD"
+ when: currentSet == 3
+ PropertyChanges {
+ target: listview
+ move: d_move
+ moveDisplaced: d_moveDisplaced
+ }
+ PropertyChanges {
+ target: root
+ useStock: true
+ }
+ }
+ ]
+
+ /* Transitions */
+ Transition {
+ id: a_add
+ ParallelAnimation {
+ NumberAnimation { target: a_add.ViewTransition.item; properties: "opacity"; from: 0; to: 1; duration: 1000 }
+ }
+ }
+ Transition {
+ id: a_remove
+ SequentialAnimation {
+ NumberAnimation { target: a_remove.ViewTransition.item; properties: "opacity"; from: 1; to: 0; duration: 1000 }
+ }
+ }
+ Transition {
+ id: a_move
+ ColorAnimation { target: a_move.ViewTransition.item; properties: "color"; to: "lightsteelblue"; duration: 1000 }
+ PathAnimation {
+ duration: 1000
+ target: a_move.ViewTransition.item
+ path: Path {
+ PathCurve { x: a_move.ViewTransition.destination.x + 150; y: a_move.ViewTransition.destination.y + 100 }
+ PathCurve { x: a_move.ViewTransition.destination.x + 150; y: a_move.ViewTransition.destination.y }
+ PathCurve { x: a_move.ViewTransition.destination.x; y: a_move.ViewTransition.destination.y }
+ }
+ }
+ }
+ Transition {
+ id: a_displaced
+ PropertyAction { target: a_displaced.ViewTransition.item; property: "color"; value: "lightsteelblue" }
+ ParallelAnimation {
+ NumberAnimation { target: a_displaced.ViewTransition.item; property: "opacity"; to: 1; duration: 250 }
+ SequentialAnimation {
+ PauseAnimation { duration: a_displaced.ViewTransition.index * 200 }
+ NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutQuad }
+ }
+ }
+ }
+
+
+ Transition {
+ id: b_add
+ SequentialAnimation {
+ NumberAnimation { target: b_add.ViewTransition.item; properties: "scale"; from: 1; to: 1.3; duration: 100 }
+ NumberAnimation { target: b_add.ViewTransition.item; properties: "scale"; from: 1.3; to: 1; duration: 500; easing.type: Easing.OutBounce }
+ }
+ }
+ Transition {
+ id: b_move
+ SequentialAnimation {
+ PauseAnimation { duration: b_move.ViewTransition.index * 100 }
+ ParallelAnimation {
+ ColorAnimation { target: b_move.ViewTransition.item; properties: "color"; from: "red"; to: "lightsteelblue"; duration: 2000 }
+ SequentialAnimation {
+ PathAnimation {
+ duration: 1000
+ target: b_move.ViewTransition.item
+ path: Path {
+ PathCurve { x: b_move.ViewTransition.destination.x + 150; y: b_move.ViewTransition.destination.y + 100 }
+ PathCurve { relativeX: 30; relativeY: -100 }
+ }
+ }
+ NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutBounce }
+ }
+ }
+ }
+ }
+ Transition {
+ id: b_remove
+ SequentialAnimation {
+ NumberAnimation { target: b_remove.ViewTransition.item; properties: "opacity"; from: 1; to: 0; duration: 1000 }
+ }
+ }
+ Transition {
+ id: b_displaced
+ PropertyAction { target: b_displaced.ViewTransition.item; property: "color"; value: "lightsteelblue" }
+ SequentialAnimation {
+ PauseAnimation { duration: b_displaced.ViewTransition.item.x == 0 ? b_displaced.ViewTransition.index * 200 : 0 }
+ NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutBounce }
+ }
+ }
+
+
+ Transition {
+ id: c_add
+ NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 }
+ NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 }
+ property int xoff
+ xoff: c_add.ViewTransition.index % 2 == 0 ? 200 : -200
+ PathAnimation {
+ duration: 1000
+ path: Path {
+ startX: c_add.ViewTransition.destination.x + c_add.xoff
+ startY: c_add.ViewTransition.destination.y + 200
+ PathCurve { relativeX: -100; relativeY: -50 }
+ PathCurve { relativeX: 50; relativeY: -150 }
+ PathCurve {
+ x: c_add.ViewTransition.destination.x
+ y: c_add.ViewTransition.destination.y
+ }
+ }
+ }
+ }
+ Transition {
+ id: c_move
+ ColorAnimation { target: c_move.ViewTransition.item; properties: "color"; from: "red"; to: "lightsteelblue"; duration: 1000 }
+ PathAnimation {
+ duration: 1000
+ target: c_move.ViewTransition.item
+ path: Path {
+ PathCurve { x: c_move.ViewTransition.destination.x + 150; y: c_move.ViewTransition.destination.y + 100 }
+ PathCurve { x: c_move.ViewTransition.destination.x + 150; y: c_move.ViewTransition.destination.y }
+ PathCurve { x: c_move.ViewTransition.destination.x; y: c_move.ViewTransition.destination.y }
+ }
+ }
+ }
+ Transition {
+ id: c_remove
+ PropertyAnimation { target: c_remove.ViewTransition.item; properties: "opacity"; to: 0; duration: 3000; easing.type: Easing.OutInBounce }
+ }
+ Transition {
+ id: c_addDisplaced
+
+ PropertyAction { property: "color"; value: "lightsteelblue" }
+ PropertyAction { property: "opacity"; value: 1.0 }
+ PropertyAction { property: "scale"; value: 1.0 }
+ SequentialAnimation {
+ PauseAnimation { duration: c_addDisplaced.ViewTransition.index * 200 }
+ NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutElastic }
+ }
+
+ }
+ Transition {
+ id: c_moveDisplaced
+
+ PropertyAction { property: "color"; value: "lightsteelblue" }
+ PropertyAction { property: "opacity"; value: 1.0 }
+ PropertyAction { property: "scale"; value: 1.0 }
+ SequentialAnimation {
+ NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutBounce }
+ }
+
+ }
+ Transition {
+ id: c_removeDisplaced
+
+ PropertyAction { property: "color"; value: "lightsteelblue" }
+ PropertyAction { property: "opacity"; value: 1.0 }
+ PropertyAction { property: "scale"; value: 1.0 }
+ SequentialAnimation {
+ PauseAnimation { duration: (c_removeDisplaced.ViewTransition.index * 200) + 3000 }
+ NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutElastic }
+ }
+
+ }
+ Transition {
+ id: d_move
+ SequentialAnimation {
+ PropertyAction { target: d_move.ViewTransition.item; property: "movn"; value: true }
+ ParallelAnimation {
+ NumberAnimation { target: d_move.ViewTransition.item; properties: "opacity"; to: 0; duration: 2000 }
+ NumberAnimation { target: d_move.ViewTransition.item; properties: "parts"; to: 500; duration: 2000 }
+ }
+ NumberAnimation { properties: "x,y"; duration: 1000*(d_move.ViewTransition.index+1) }
+ ParallelAnimation {
+ NumberAnimation { target: d_move.ViewTransition.item; properties: "opacity"; to: 1; duration: 2000 }
+ NumberAnimation { target: d_move.ViewTransition.item; properties: "parts"; to: 0; duration: 2000 }
+ }
+ PropertyAction { target: d_move.ViewTransition.item; property: "movn"; value: false }
+ }
+ }
+
+ Transition {
+ id: d_moveDisplaced
+ PropertyAction { target: d_moveDisplaced.ViewTransition.item; property: "color"; value: "lightsteelblue" }
+ SequentialAnimation {
+ PauseAnimation { duration: 500*(d_moveDisplaced.ViewTransition.index+1) }
+ NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutQuad }
+ }
+ }
+
+ /* Buttons */
+ Column {
+ spacing: 2
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "To Top" }
+ MouseArea { anchors.fill: parent; onClicked: listview.model.move(listview.currentIndex, 0, 1) }
+ }
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "Add" }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: listview.model.insert(listview.currentIndex+1, {"name": "New item", "original": false } )
+ }
+ }
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "Remove" }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: listview.model.remove(listview.currentIndex)
+ }
+ }
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "Append" }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: listview.model.append({"name": "New item", "original": false })
+ }
+ }
+ }
+ Column {
+ spacing: 2
+ anchors.right: parent.right
+ anchors.rightMargin: 2
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: currentSet == 0 ? "green" : "lightgray"
+ ColorAnimation on color { duration: 1000 }
+ }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "Set A" }
+ MouseArea { anchors.fill: parent; onClicked: { currentSet = 0 } }
+ }
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: currentSet == 1 ? "green" : "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "Set B" }
+ MouseArea { anchors.fill: parent; onClicked: { currentSet = 1 } }
+ }
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: currentSet == 2 ? "green" : "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "Set C" }
+ MouseArea { anchors.fill: parent; onClicked: { currentSet = 2 } }
+ }
+ Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "darkgray" }
+ GradientStop { position: 0.5; color: currentSet == 3 ? "green" : "lightgray" }
+ GradientStop { position: 1.0; color: "darkgray" }
+ }
+ radius: 6
+ border.color: "black"
+ height: 50; width: 80
+ Text { anchors.centerIn: parent; text: "Set D" }
+ MouseArea { anchors.fill: parent; onClicked: { currentSet = 3 } }
+ }
+ }
+}
diff --git a/tools/easingcurveeditor/easingcurveeditor.pro b/tools/easingcurveeditor/easingcurveeditor.pro
index 0a266d0aee..fa5aea8418 100644
--- a/tools/easingcurveeditor/easingcurveeditor.pro
+++ b/tools/easingcurveeditor/easingcurveeditor.pro
@@ -16,8 +16,6 @@ RESOURCES = $$PWD/resources.qrc
HEADERS += \
splineeditor.h \
mainwindow.h \
- ui_properties.h \
- ui_pane.h \
segmentproperties.h
FORMS += \
diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro
index 7662fd79c8..9cda82588f 100644
--- a/tools/qmlplugindump/qmlplugindump.pro
+++ b/tools/qmlplugindump/qmlplugindump.pro
@@ -23,15 +23,15 @@ macx: QMAKE_INFO_PLIST = Info.plist
contains(QT_CONFIG,debug):contains(QT_CONFIG,release) {
CONFIG += debug_and_release build_all
+ CONFIG(debug, debug|release) {
+ win32: TARGET = $$join(TARGET,,,d)
+ }
} else {
contains(QT_CONFIG,debug): CONFIG += debug
contains(QT_CONFIG,release): CONFIG += release
}
}
-CONFIG(debug, debug|release) {
- win32: TARGET = $$join(TARGET,,,d)
-}
target.path = $$[QT_INSTALL_BINS]
INSTALLS += target
diff --git a/tools/qmlprofiler/qmlprofiler.pro b/tools/qmlprofiler/qmlprofiler.pro
index c35c487a1d..b90554455f 100644
--- a/tools/qmlprofiler/qmlprofiler.pro
+++ b/tools/qmlprofiler/qmlprofiler.pro
@@ -9,14 +9,15 @@ INSTALLS += target
macx: CONFIG -= app_bundle
-CONFIG += console declarative_debug
+CONFIG += console
SOURCES += main.cpp \
qmlprofilerapplication.cpp \
commandlistener.cpp \
qqmldebugclient.cpp \
qmlprofilerdata.cpp \
- qmlprofilerclient.cpp
+ qmlprofilerclient.cpp \
+ qpacketprotocol.cpp
HEADERS += \
qmlprofilerapplication.h \
@@ -25,4 +26,5 @@ HEADERS += \
qmlprofilerdata.h \
qmlprofilerclient.h \
qmlprofilereventlocation.h \
- qqmldebugclient.h
+ qqmldebugclient.h \
+ qpacketprotocol.h
diff --git a/tools/qmlprofiler/qpacketprotocol.cpp b/tools/qmlprofiler/qpacketprotocol.cpp
new file mode 100644
index 0000000000..1dd079ca6a
--- /dev/null
+++ b/tools/qmlprofiler/qpacketprotocol.cpp
@@ -0,0 +1,546 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpacketprotocol.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QElapsedTimer>
+
+static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
+
+/*!
+ \class QPacketProtocol
+ \internal
+
+ \brief The QPacketProtocol class encapsulates communicating discrete packets
+ across fragmented IO channels, such as TCP sockets.
+
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ fragmented transports such as TCP and UDP.
+
+ As transmission boundaries are not respected, sending packets over protocols
+ like TCP frequently involves "stitching" them back together at the receiver.
+ QPacketProtocol makes this easier by performing this task for you. Packet
+ data sent using QPacketProtocol is prepended with a 4-byte size header
+ allowing the receiving QPacketProtocol to buffer the packet internally until
+ it has all been received. QPacketProtocol does not perform any sanity
+ checking on the size or on the data, so this class should only be used in
+ prototyping or trusted situations where DOS attacks are unlikely.
+
+ QPacketProtocol does not perform any communications itself. Instead it can
+ operate on any QIODevice that supports the QIODevice::readyRead() signal. A
+ logical "packet" is encapsulated by the companion QPacket class. The
+ following example shows two ways to send data using QPacketProtocol. The
+ transmitted data is equivalent in both.
+
+ \code
+ QTcpSocket socket;
+ // ... connect socket ...
+
+ QPacketProtocol protocol(&socket);
+
+ // Send packet the quick way
+ protocol.send() << "Hello world" << 123;
+
+ // Send packet the longer way
+ QPacket packet;
+ packet << "Hello world" << 123;
+ protocol.send(packet);
+ \endcode
+
+ Likewise, the following shows how to read data from QPacketProtocol, assuming
+ that the QPacketProtocol::readyRead() signal has been emitted.
+
+ \code
+ // ... QPacketProtocol::readyRead() is emitted ...
+
+ int a;
+ QByteArray b;
+
+ // Receive packet the quick way
+ protocol.read() >> a >> b;
+
+ // Receive packet the longer way
+ QPacket packet = protocol.read();
+ p >> a >> b;
+ \endcode
+
+ \ingroup io
+ \sa QPacket
+*/
+
+class QPacketProtocolPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
+ : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
+ waitingForPacket(false), dev(_dev)
+ {
+ Q_ASSERT(4 == sizeof(qint32));
+
+ QObject::connect(this, SIGNAL(readyRead()),
+ parent, SIGNAL(readyRead()));
+ QObject::connect(this, SIGNAL(packetWritten()),
+ parent, SIGNAL(packetWritten()));
+ QObject::connect(this, SIGNAL(invalidPacket()),
+ parent, SIGNAL(invalidPacket()));
+ QObject::connect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::connect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ }
+
+Q_SIGNALS:
+ void readyRead();
+ void packetWritten();
+ void invalidPacket();
+
+public Q_SLOTS:
+ void aboutToClose()
+ {
+ inProgress.clear();
+ sendingPackets.clear();
+ inProgressSize = -1;
+ }
+
+ void bytesWritten(qint64 bytes)
+ {
+ Q_ASSERT(!sendingPackets.isEmpty());
+
+ while (bytes) {
+ if (sendingPackets.at(0) > bytes) {
+ sendingPackets[0] -= bytes;
+ bytes = 0;
+ } else {
+ bytes -= sendingPackets.at(0);
+ sendingPackets.removeFirst();
+ emit packetWritten();
+ }
+ }
+ }
+
+ void readyToRead()
+ {
+ while (true) {
+ // Need to get trailing data
+ if (-1 == inProgressSize) {
+ // We need a size header of sizeof(qint32)
+ if (sizeof(qint32) > (uint)dev->bytesAvailable())
+ return;
+
+ // Read size header
+ int read = dev->read((char *)&inProgressSize, sizeof(qint32));
+ Q_ASSERT(read == sizeof(qint32));
+ Q_UNUSED(read);
+
+ // Check sizing constraints
+ if (inProgressSize > maxPacketSize) {
+ QObject::disconnect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::disconnect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ dev = 0;
+ emit invalidPacket();
+ return;
+ }
+
+ inProgressSize -= sizeof(qint32);
+ } else {
+ inProgress.append(dev->read(inProgressSize - inProgress.size()));
+
+ if (inProgressSize == inProgress.size()) {
+ // Packet has arrived!
+ packets.append(inProgress);
+ inProgressSize = -1;
+ inProgress.clear();
+
+ waitingForPacket = false;
+ emit readyRead();
+ } else
+ return;
+ }
+ }
+ }
+
+public:
+ QList<qint64> sendingPackets;
+ QList<QByteArray> packets;
+ QByteArray inProgress;
+ qint32 inProgressSize;
+ qint32 maxPacketSize;
+ bool waitingForPacket;
+ QIODevice *dev;
+};
+
+/*!
+ Construct a QPacketProtocol instance that works on \a dev with the
+ specified \a parent.
+ */
+QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
+ : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
+{
+ Q_ASSERT(dev);
+}
+
+/*!
+ Destroys the QPacketProtocol instance.
+ */
+QPacketProtocol::~QPacketProtocol()
+{
+}
+
+/*!
+ Returns the maximum packet size allowed. By default this is
+ 2,147,483,647 bytes.
+
+ If a packet claiming to be larger than the maximum packet size is received,
+ the QPacketProtocol::invalidPacket() signal is emitted.
+
+ \sa QPacketProtocol::setMaximumPacketSize()
+ */
+qint32 QPacketProtocol::maximumPacketSize() const
+{
+ return d->maxPacketSize;
+}
+
+/*!
+ Sets the maximum allowable packet size to \a max.
+
+ \sa QPacketProtocol::maximumPacketSize()
+ */
+qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
+{
+ if (max > (signed)sizeof(qint32))
+ d->maxPacketSize = max;
+ return d->maxPacketSize;
+}
+
+/*!
+ Returns a streamable object that is transmitted on destruction. For example
+
+ \code
+ protocol.send() << "Hello world" << 123;
+ \endcode
+
+ will send a packet containing "Hello world" and 123. To construct more
+ complex packets, explicitly construct a QPacket instance.
+ */
+QPacketAutoSend QPacketProtocol::send()
+{
+ return QPacketAutoSend(this);
+}
+
+/*!
+ \fn void QPacketProtocol::send(const QPacket & packet)
+
+ Transmit the \a packet.
+ */
+void QPacketProtocol::send(const QPacket & p)
+{
+ if (p.b.isEmpty())
+ return; // We don't send empty packets
+
+ qint64 sendSize = p.b.size() + sizeof(qint32);
+
+ d->sendingPackets.append(sendSize);
+ qint32 sendSize32 = sendSize;
+ qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_ASSERT(writeBytes == sizeof(qint32));
+ writeBytes = d->dev->write(p.b);
+ Q_ASSERT(writeBytes == p.b.size());
+}
+
+/*!
+ Returns the number of received packets yet to be read.
+ */
+qint64 QPacketProtocol::packetsAvailable() const
+{
+ return d->packets.count();
+}
+
+/*!
+ Discard any unread packets.
+ */
+void QPacketProtocol::clear()
+{
+ d->packets.clear();
+}
+
+/*!
+ Return the next unread packet, or an invalid QPacket instance if no packets
+ are available. This method does NOT block.
+ */
+QPacket QPacketProtocol::read()
+{
+ if (0 == d->packets.count())
+ return QPacket();
+
+ QPacket rv(d->packets.at(0));
+ d->packets.removeFirst();
+ return rv;
+}
+
+/*
+ Returns the difference between msecs and elapsed. If msecs is -1,
+ however, -1 is returned.
+*/
+static int qt_timeout_value(int msecs, int elapsed)
+{
+ if (msecs == -1)
+ return -1;
+
+ int timeout = msecs - elapsed;
+ return timeout < 0 ? 0 : timeout;
+}
+
+/*!
+ This function locks until a new packet is available for reading and the
+ \l{QIODevice::}{readyRead()} signal has been emitted. The function
+ will timeout after \a msecs milliseconds; the default timeout is
+ 30000 milliseconds.
+
+ The function returns true if the readyRead() signal is emitted and
+ there is new data available for reading; otherwise it returns false
+ (if an error occurred or the operation timed out).
+ */
+
+bool QPacketProtocol::waitForReadyRead(int msecs)
+{
+ if (!d->packets.isEmpty())
+ return true;
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ d->waitingForPacket = true;
+ do {
+ if (!d->dev->waitForReadyRead(msecs))
+ return false;
+ if (!d->waitingForPacket)
+ return true;
+ msecs = qt_timeout_value(msecs, stopWatch.elapsed());
+ } while (true);
+}
+
+/*!
+ Return the QIODevice passed to the QPacketProtocol constructor.
+*/
+QIODevice *QPacketProtocol::device()
+{
+ return d->dev;
+}
+
+/*!
+ \fn void QPacketProtocol::readyRead()
+
+ Emitted whenever a new packet is received. Applications may use
+ QPacketProtocol::read() to retrieve this packet.
+ */
+
+/*!
+ \fn void QPacketProtocol::invalidPacket()
+
+ A packet larger than the maximum allowable packet size was received. The
+ packet will be discarded and, as it indicates corruption in the protocol, no
+ further packets will be received.
+ */
+
+/*!
+ \fn void QPacketProtocol::packetWritten()
+
+ Emitted each time a packet is completing written to the device. This signal
+ may be used for communications flow control.
+ */
+
+/*!
+ \class QPacket
+ \internal
+
+ \brief The QPacket class encapsulates an unfragmentable packet of data to be
+ transmitted by QPacketProtocol.
+
+ The QPacket class works together with QPacketProtocol to make it simple to
+ send arbitrary sized data "packets" across fragmented transports such as TCP
+ and UDP.
+
+ QPacket provides a QDataStream interface to an unfragmentable packet.
+ Applications should construct a QPacket, propagate it with data and then
+ transmit it over a QPacketProtocol instance. For example:
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket myPacket;
+ myPacket << "Hello world!" << 123;
+ protocol.send(myPacket);
+ \endcode
+
+ As long as both ends of the connection are using the QPacketProtocol class,
+ the data within this packet will be delivered unfragmented at the other end,
+ ready for extraction.
+
+ \code
+ QByteArray greeting;
+ int count;
+
+ QPacket myPacket = protocol.read();
+
+ myPacket >> greeting >> count;
+ \endcode
+
+ Only packets returned from QPacketProtocol::read() may be read from. QPacket
+ instances constructed by directly by applications are for transmission only
+ and are considered "write only". Attempting to read data from them will
+ result in undefined behavior.
+
+ \ingroup io
+ \sa QPacketProtocol
+ */
+
+/*!
+ Constructs an empty write-only packet.
+ */
+QPacket::QPacket()
+ : QDataStream(), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::WriteOnly);
+ setDevice(buf);
+ setVersion(QDataStream::Qt_4_7);
+}
+
+/*!
+ Destroys the QPacket instance.
+ */
+QPacket::~QPacket()
+{
+ if (buf) {
+ delete buf;
+ buf = 0;
+ }
+}
+
+/*!
+ Creates a copy of \a other. The initial stream positions are shared, but the
+ two packets are otherwise independent.
+ */
+QPacket::QPacket(const QPacket & other)
+ : QDataStream(), b(other.b), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(other.buf->openMode());
+ setDevice(buf);
+}
+
+/*!
+ \internal
+ */
+QPacket::QPacket(const QByteArray & ba)
+ : QDataStream(), b(ba), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::ReadOnly);
+ setDevice(buf);
+}
+
+/*!
+ Returns true if this packet is empty - that is, contains no data.
+ */
+bool QPacket::isEmpty() const
+{
+ return b.isEmpty();
+}
+
+/*!
+ Returns raw packet data.
+ */
+QByteArray QPacket::data() const
+{
+ return b;
+}
+
+/*!
+ Clears data in the packet. This is useful for reusing one writable packet.
+ For example
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket packet;
+
+ packet << "Hello world!" << 123;
+ protocol.send(packet);
+
+ packet.clear();
+ packet << "Goodbyte world!" << 789;
+ protocol.send(packet);
+ \endcode
+ */
+void QPacket::clear()
+{
+ QBuffer::OpenMode oldMode = buf->openMode();
+ buf->close();
+ b.clear();
+ buf->setBuffer(&b); // reset QBuffer internals with new size of b.
+ buf->open(oldMode);
+}
+
+/*!
+ \class QPacketAutoSend
+ \internal
+
+ \internal
+ */
+QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p)
+ : QPacket(), p(_p)
+{
+}
+
+QPacketAutoSend::~QPacketAutoSend()
+{
+ if (!b.isEmpty())
+ p->send(*this);
+}
+
+#include <qpacketprotocol.moc>
diff --git a/tools/qmlprofiler/qpacketprotocol.h b/tools/qmlprofiler/qpacketprotocol.h
new file mode 100644
index 0000000000..be5fa28104
--- /dev/null
+++ b/tools/qmlprofiler/qpacketprotocol.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPACKETPROTOCOL_H
+#define QPACKETPROTOCOL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+class QBuffer;
+QT_END_NAMESPACE
+class QPacket;
+class QPacketAutoSend;
+class QPacketProtocolPrivate;
+
+class QPacketProtocol : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0);
+ virtual ~QPacketProtocol();
+
+ qint32 maximumPacketSize() const;
+ qint32 setMaximumPacketSize(qint32);
+
+ QPacketAutoSend send();
+ void send(const QPacket &);
+
+ qint64 packetsAvailable() const;
+ QPacket read();
+
+ bool waitForReadyRead(int msecs = 3000);
+
+ void clear();
+
+ QIODevice *device();
+
+Q_SIGNALS:
+ void readyRead();
+ void invalidPacket();
+ void packetWritten();
+
+private:
+ QPacketProtocolPrivate *d;
+};
+
+
+class QPacket : public QDataStream
+{
+public:
+ QPacket();
+ QPacket(const QPacket &);
+ virtual ~QPacket();
+
+ void clear();
+ bool isEmpty() const;
+ QByteArray data() const;
+
+protected:
+ friend class QPacketProtocol;
+ QPacket(const QByteArray &ba);
+ QByteArray b;
+ QBuffer *buf;
+};
+
+class QPacketAutoSend : public QPacket
+{
+public:
+ virtual ~QPacketAutoSend();
+
+private:
+ friend class QPacketProtocol;
+ QPacketAutoSend(QPacketProtocol *);
+ QPacketProtocol *p;
+};
+
+#endif
diff --git a/tools/qmlprofiler/qqmldebugclient.cpp b/tools/qmlprofiler/qqmldebugclient.cpp
index 0453f88350..36402be5a8 100644
--- a/tools/qmlprofiler/qqmldebugclient.cpp
+++ b/tools/qmlprofiler/qqmldebugclient.cpp
@@ -40,8 +40,7 @@
****************************************************************************/
#include "qqmldebugclient.h"
-
-#include <private/qpacketprotocol_p.h>
+#include "qpacketprotocol.h"
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 327dfc6889..32c9be7f46 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -156,6 +156,7 @@ struct Options
, clip(false)
, versionDetection(true)
, slowAnimations(false)
+ , quitImmediately(false)
{
}
@@ -168,6 +169,7 @@ struct Options
bool clip;
bool versionDetection;
bool slowAnimations;
+ bool quitImmediately;
};
#if defined(QMLSCENE_BUNDLE)
@@ -347,6 +349,7 @@ static void usage()
qWarning(" --no-multisample .......................... Disable multisampling (anti-aliasing)");
qWarning(" --no-version-detection .................... Do not try to detect the version of the .qml file");
qWarning(" --slow-animations ......................... Run all animations in slow motion");
+ qWarning(" --quit .................................... Quit immediately after starting");
qWarning(" ");
exit(1);
@@ -372,6 +375,8 @@ int main(int argc, char ** argv)
options.versionDetection = false;
else if (lowerArgument == QLatin1String("--slow-animations"))
options.slowAnimations = true;
+ else if (lowerArgument == QLatin1String("--quit"))
+ options.quitImmediately = true;
else if (lowerArgument == QLatin1String("-i") && i + 1 < argc)
imports.append(QString::fromLatin1(argv[++i]));
else if (lowerArgument == QLatin1String("--help")
@@ -428,6 +433,10 @@ int main(int argc, char ** argv)
else
window->show();
+ if (options.quitImmediately) {
+ QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
+ }
+
exitCode = app.exec();
delete window;